This document is the summary of the R for Cognitive Psychologists workshop.
All correspondence related to this document should be addressed to:
Omid Ghasemi (Macquarie University, Sydney, NSW, 2109, AUSTRALIA)
Email: omidreza.ghasemi@hdr.mq.edu.au
Research Question
The aim of the study is to test if simple arguments are more effective in belief revision than more complex arguments. To that end, we present participants with an imaginary scenario (two alien creatures on a planet) and a theory (one creature is predator and the other one is prey) and we ask them to rate the likelihood truth of the theory based on a simple fact (We adapted this method from Gregg et al.,2017; see the original study here). Then, in a between-subject manipulation, participants will be presented with either 6 simple arguments (Modus Ponens conditionals) or 6 more complex arguments (Modus Tollens conditionals), and they will be asked to rate the likelihood truth of the initial theory on 7 stages.
The first stage is the base rating stage. The next three stages include supportive arguments of the theory and the last three arguments include disproving arguments of the theory. We hypothesized that the group with simple arguments shows better persuasion (as it reflects in higher ratings for the supportive arguments) and better dissuasion (as it reflects in lower ratings for the opposing arguments).
In the last part of the study, participants will be asked to answer several cognitive capacity/style measures including CRT, AOT-E, mindware, and numeracy scales. We hypothesized that cognitive ability, cognitive style, and open-mindedness are positive predictors of persuasion and dissuasion. These associations should be more pronounced for participants in the group with complex arguments because the ability and willingness to engage in deliberative thinking may favor participants to assess the underlying logical structure of those arguments. However, for participants in the simple group, the logical structure of arguments is more evident, so participants with lower ability can still assess the logical status of those arguments.

Thus, our hypotheses for this experiment are as follows:
Participants in the group with simple arguments have higher ratings for supportive arguments (They are more easily persuaded than those in the group with complex arguments).
Participants in the group with simple arguments have lower ratings for opposing arguments (They are more easily dissuaded than those in the group with complex arguments).
There are significant associations between CRT, AOT-E, Numeracy, and mindware with both persuasion and dissuasion indexes in each group and in the entire sample. The relationship between these measures should be stronger, although not significantly, for participants in the group with complex arguments.

Getting Ready
First, we need to design the experiment. For this experiment, we use online platforms for data collection. There are several options such as Gorilla, JSpsych, Qualtrics, psychoJS (pavlovia), etc. Since we do not need any reaction time data, we simply use Qualtrics. For an overview of different lab-based and online platforms, see here.
Next, we need to decide on the number of participants (sample size). For this study, we do not sue power analysis since we cannot access more than 120 participants. However, it is highly suggested calculate sample size using power estimation. You can find some nice tutorials on how to do that here, here, and here.
After we created the experiment and decided on the sample size, the next step is to preresigter the study. However, it would be better to do a pilot with 4 or 5 participants, clean all the data, do the desired analysis, and then pre-register the analysis and those codes. You can find the preregistration form for the current study here.
Finally, we need to restructure our project in a tidy folder with different sub-folders. Having a clean and tidy folder structure can save us! There are different formats of folder structure (for example, see here and here), but for now, we use the following structure:

Introduction to R
# load libraries
library(tidyverse)
library(here)
library(janitor)
library(broom)
library(afex)
library(emmeans)
library(knitr)
library(kableExtra)
library(ggsci)
library(patchwork)
library(skimr)
# install.packages("devtools")
# devtools::install_github("easystats/correlation")
library("correlation")
options(scipen=999) # turn off scientific notations
options(contrasts = c('contr.sum','contr.poly')) # set the contrast sum globally
options(knitr.kable.NA = '')
R can be used as a calculator. For mathematical purposes, be careful of the order in which R executes the commands.
10 + 10
## [1] 20
4 ^ 2
## [1] 16
(250 / 500) * 100
## [1] 50
R is a bit flexible with spacing (but no spacing in the name of variables and words)
10+10
## [1] 20
10 + 10
## [1] 20
R can sometimes tell that you’re not finished yet
10 +
How to create a variable? Variable assignment using <- and =. Note that R is case sensitive for everything
pay <- 250
month = 12
pay * month
## [1] 3000
salary <- pay * month
Few points in naming variables and vectors: use short, informative words, keep same method (e.g., not using capital words, use only _ or . ).
Function
Function is a set of statements combined together to perform a specific task. When we use a block of code repeatedly, we can convert it to a function. To write a function, first, you need to define it:
my_multiplier <- function(a,b){
result = a * b
return (result)
}
This code do nothing. To get a result, you need to call it:
my_multiplier (2,4)
## [1] 8
Fortunately, you do not need to write everything from scratch. R has lots of built-in functions that you can use:
round(54.6787)
## [1] 55
round(54.5787, digits = 2)
## [1] 54.58
Use ? before the function name to get some help. For example, ?round. You will see many functions in the rest of the workshop.
Basic Data Types in R:
function class() is used to show what is the type of a variable.
- Logical:
TRUE, FALSE can be abbreviated as T, F. They has to be capital, ‘true’ is not a logical data:
class(TRUE)
## [1] "logical"
class(F)
## [1] "logical"
- Numeric: all numbers e.g. 5, 10.5, 11,37; a special type of numeric is “integer” which is numbers without decimal. Integers are always numeric, but numeric is not always integer:
class(2)
## [1] "numeric"
class(13.46)
## [1] "numeric"
- Character: text for example, “I love R” or “4” or “4.5”:
class("ha ha ha ha")
## [1] "character"
class("56.6")
## [1] "character"
class("TRUE")
## [1] "character"
Can we change the type of data in a variable? Yes, you need to use the function as.---()
as.numeric(TRUE)
## [1] 1
as.character(4)
## [1] "4"
as.numeric("4.5")
## [1] 4.5
as.numeric("Hello")
## Warning: NAs introduced by coercion
## [1] NA
Data Structures in R
Vector: when there are more than one number or letter stored. Use the combine function c() for that.
sale <- c(1, 2, 3,4, 5, 6, 7, 8, 9, 10) # also sale <- c(1:10)
sale <- c(1:10)
sale * sale
## [1] 1 4 9 16 25 36 49 64 81 100
Subsetting a vector:
days <- c("Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday")
days[2]
## [1] "Sunday"
days[-2]
## [1] "Saturday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday"
days[c(2, 3, 4)]
## [1] "Sunday" "Monday" "Tuesday"
Exercise:
Create a vector named my_vector with numbers from 0 to 1000 in it:
my_vector <- (0:1000)
mean(my_vector)
## [1] 500
median(my_vector)
## [1] 500
min(my_vector)
## [1] 0
range(my_vector)
## [1] 0 1000
class(my_vector)
## [1] "integer"
sum(my_vector)
## [1] 500500
sd(my_vector)
## [1] 289.1081
List: allows you to gather a variety of objects under one name (that is, the name of the list) in an ordered way. These objects can be matrices, vectors, data frames, even other list.
my_list = list(sale, 1, 3, 4:7, "HELLO", "hello", FALSE)
my_list
## [[1]]
## [1] 1 2 3 4 5 6 7 8 9 10
##
## [[2]]
## [1] 1
##
## [[3]]
## [1] 3
##
## [[4]]
## [1] 4 5 6 7
##
## [[5]]
## [1] "HELLO"
##
## [[6]]
## [1] "hello"
##
## [[7]]
## [1] FALSE
Factor: Factors store the vector along with the distinct values of the elements in the vector as labels. The labels are always character irrespective of whether it is numeric or character. For example, variable gender with “male” and “female” entries:
gender <- c("male", "male", "male", "female", "female", "female")
gender <- factor(gender)
R now treats gender as a nominal (categorical) variable: 1=female, 2=male internally (alphabetically).
summary(gender)
## female male
## 3 3
Question: why when we ran the above function i.e. summary(), it showed three and not two levels of the data? Hint: run ‘gender’.
gender
## [1] male male male female female female
## Levels: female male
So, be careful of spaces!
Exercise:
Create a gender factor with 30 male and 40 females (Hint: use the rep() function):
gender <- c(rep("male",30), rep("female", 40))
gender <- factor(gender)
gender
## [1] male male male male male male male male male male
## [11] male male male male male male male male male male
## [21] male male male male male male male male male male
## [31] female female female female female female female female female female
## [41] female female female female female female female female female female
## [51] female female female female female female female female female female
## [61] female female female female female female female female female female
## Levels: female male
There are two types of categorical variables: nominal and ordinal. How to create ordered factors (when the variable is nominal and values can be ordered)? We should add two additional arguments to the factor() function: ordered = TRUE, and levels = c("level1", "level2"). For example, we have a vector that shows participants’ education level.
edu<-c(3,2,3,4,1,2,2,3,4)
education<-factor(edu, ordered = TRUE)
levels(education) <- c("Primary school","high school","College","Uni graduated")
education
## [1] College high school College Uni graduated
## [5] Primary school high school high school College
## [9] Uni graduated
## Levels: Primary school < high school < College < Uni graduated
Exercise:
We have a factor with patient and control values. Here, the first level is control and the second level is patient. Change the order of levels, so patient would be the first level:
health_status <- factor(c(rep('patient',5),rep('control',5)))
health_status
## [1] patient patient patient patient patient control control control
## [9] control control
## Levels: control patient
health_status_reordered <- factor(health_status, levels = c('patient','control'))
health_status_reordered
## [1] patient patient patient patient patient control control control
## [9] control control
## Levels: patient control
Finally, can you relabel both levels to uppercase characters? (Hint: check ?factor)
health_status_relabeled <- factor(health_status, levels = c('patient','control'), labels = c('Patient','Control'))
health_status_relabeled
## [1] Patient Patient Patient Patient Patient Control Control Control
## [9] Control Control
## Levels: Patient Control
Matrices: All columns in a matrix must have the same mode(numeric, character, etc.) and the same length. It can be created using a vector input to the matrix function.
my_matrix = matrix(c(1,2,3,4,5,6,7,8,9), nrow = 3, ncol = 3)
my_matrix
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
Data frames: (two-dimensional objects) can hold numeric, character or logical values. Within a column all elements have the same data type, but different columns can be of different data type. Let’s create a dataframe:
id <- 1:200
group <- c(rep("Psychotherapy", 100), rep("Medication", 100))
response <- c(rnorm(100, mean = 30, sd = 5),
rnorm(100, mean = 25, sd = 5))
my_dataframe <-data.frame(Patient = id,
Treatment = group,
Response = response)
We also could have done the below
my_dataframe <-data.frame(Patient = c(1:200),
Treatment = c(rep("Psychotherapy", 100), rep("Medication", 100)),
Response = c(rnorm(100, mean = 30, sd = 5),
rnorm(100, mean = 25, sd = 5)))
In large data sets, the function head() enables you to show the first observations of a data frames. Similarly, the function tail() prints out the last observations in your data set.
head(my_dataframe)
tail(my_dataframe)
|
Patient
|
Treatment
|
Response
|
|
1
|
Psychotherapy
|
27.58203
|
|
2
|
Psychotherapy
|
40.27333
|
|
3
|
Psychotherapy
|
27.84694
|
|
4
|
Psychotherapy
|
30.64339
|
|
5
|
Psychotherapy
|
24.86349
|
|
6
|
Psychotherapy
|
34.39090
|
|
|
Patient
|
Treatment
|
Response
|
|
195
|
195
|
Medication
|
26.773637
|
|
196
|
196
|
Medication
|
26.842429
|
|
197
|
197
|
Medication
|
4.893503
|
|
198
|
198
|
Medication
|
21.931324
|
|
199
|
199
|
Medication
|
22.290277
|
|
200
|
200
|
Medication
|
24.706925
|
Similar to vectors and matrices, brackets [] are used to selects data from rows and columns in data.frames:
my_dataframe[35, 3]
## [1] 30.45148
Exercise
How can we get all columns, but only for the first 10 participants?
my_dataframe[1:10, ]
|
Patient
|
Treatment
|
Response
|
|
1
|
Psychotherapy
|
27.58203
|
|
2
|
Psychotherapy
|
40.27333
|
|
3
|
Psychotherapy
|
27.84694
|
|
4
|
Psychotherapy
|
30.64339
|
|
5
|
Psychotherapy
|
24.86349
|
|
6
|
Psychotherapy
|
34.39090
|
|
7
|
Psychotherapy
|
34.37851
|
|
8
|
Psychotherapy
|
27.84487
|
|
9
|
Psychotherapy
|
34.27093
|
|
10
|
Psychotherapy
|
29.60134
|
How to get only the Response column for all participants?
my_dataframe[ , 3]
## [1] 27.582031 40.273325 27.846937 30.643390 24.863487 34.390905 34.378513
## [8] 27.844867 34.270933 29.601343 29.506148 29.591774 34.035551 34.052017
## [15] 30.186467 30.736900 30.281547 25.567961 24.268548 25.836347 34.453248
## [22] 29.437714 31.406009 34.344625 23.733631 21.401447 32.925396 26.983750
## [29] 23.788413 32.290511 28.123706 29.163194 34.794832 24.664896 30.451477
## [36] 25.965608 32.092484 30.452763 23.774094 19.098724 32.672453 36.128457
## [43] 30.539038 27.464360 32.902303 25.663699 29.585736 23.562940 31.743565
## [50] 30.710985 34.355854 36.558037 25.947355 27.333130 25.680726 32.605684
## [57] 28.803267 34.088633 27.703104 32.987860 23.595539 33.524749 34.337007
## [64] 27.234113 34.133974 29.821562 36.435441 28.147166 31.900628 39.847710
## [71] 29.391199 20.430573 32.681213 37.721400 26.520189 28.665497 31.874356
## [78] 37.378939 33.330346 35.450458 39.144716 29.823312 34.119826 28.192823
## [85] 31.339394 28.938864 24.576777 24.882451 35.256556 26.919815 38.287286
## [92] 18.056018 29.773396 19.242731 30.098830 20.144830 35.261219 31.397647
## [99] 28.653894 21.759365 22.369556 24.892434 25.576974 22.499292 25.647166
## [106] 27.286081 33.743770 24.171932 21.432839 28.401660 29.221614 23.390066
## [113] 23.355919 21.383375 20.334071 26.018469 20.753768 24.505371 19.868771
## [120] 25.617331 25.176036 28.081208 25.937894 24.780703 26.600039 27.408776
## [127] 28.610468 29.322549 20.262021 26.509712 31.147991 18.743346 26.307870
## [134] 24.932444 25.771688 20.257431 17.337364 26.970189 18.663187 27.252974
## [141] 30.706662 24.922078 26.334771 16.056194 27.647889 22.218585 20.688515
## [148] 23.967597 18.863167 26.513233 25.214950 22.550512 23.663178 29.522233
## [155] 21.573905 24.507155 21.314063 28.459504 29.941602 22.509159 26.442839
## [162] 30.682301 26.727999 34.942770 20.869862 25.425078 29.054723 20.137336
## [169] 31.184717 25.561216 13.831821 22.361297 15.948068 31.000410 26.183191
## [176] 28.846184 22.646207 22.017349 25.773211 24.060217 20.087945 25.117872
## [183] 27.936978 24.895520 24.984349 23.011492 29.108127 24.240005 22.914543
## [190] 25.762899 19.004092 24.481123 18.539821 20.178304 26.773637 26.842429
## [197] 4.893503 21.931324 22.290277 24.706925
Another easier way for selecting particular items is using their names that is more helpful than number of the rows in large data sets:
my_dataframe[ , "Response"]
# OR:
my_dataframe$Response
Data Cleaning
Now, suppose we tested 141 students. First, let’s read and check the uncleaned data:
# read the raw data
raw_data <- read_csv(here("raw_data","raw_argumentative_exp1.csv"))
head(raw_data)
|
end_date
|
status
|
ip_address
|
progress
|
duration_in_seconds
|
subject
|
recorded_date
|
response_id
|
location_latitude
|
location_longitude
|
distribution_channel
|
user_language
|
consent_form
|
age
|
gender
|
stage1_simple
|
stage2_simple
|
stage3_simple
|
stage4_simple
|
stage5_simple
|
stage6_simple
|
stage7_simple
|
stage1_complex
|
stage2_complex
|
stage3_complex
|
stage4_complex
|
stage5_complex
|
stage6_complex
|
stage7_complex
|
attention1
|
attention2
|
attention3
|
crt1
|
crt2
|
crt3
|
aote1
|
aote2
|
aote3
|
aote4
|
aote5
|
aote6
|
aote7
|
aote8
|
group
|
attention_correct
|
numeracy_total
|
mindware_total
|
|
24/9/20 22:02
|
IP Address
|
202.7.193.64
|
100
|
1517
|
subj1
|
24/9/20 22:02
|
R_1f298znjmVzcOjp
|
-33.85910
|
151.2002
|
anonymous
|
EN
|
I consent
|
18
|
Female
|
|
|
|
|
|
|
|
36
|
70
|
68
|
54
|
51
|
43
|
41
|
1
|
1
|
1
|
8
|
50
|
20
|
5
|
5
|
5
|
5
|
5
|
6
|
5
|
3
|
Complex
|
3
|
9
|
9
|
|
25/9/20 3:23
|
IP Address
|
220.245.220.94
|
100
|
1131
|
subj2
|
25/9/20 3:23
|
R_tL0A9P33Gi18I0N
|
-34.03680
|
150.6672
|
anonymous
|
EN
|
I consent
|
18
|
Male
|
50
|
55
|
55
|
90
|
75
|
50
|
35
|
|
|
|
|
|
|
|
1
|
1
|
1
|
8
|
10
|
39
|
6
|
6
|
6
|
5
|
6
|
6
|
5
|
6
|
Simple
|
3
|
9
|
10
|
|
27/9/20 22:59
|
IP Address
|
121.210.0.211
|
100
|
709
|
subj3
|
27/9/20 22:59
|
R_1LNyJhCKxTAAMOW
|
-33.85910
|
151.2002
|
anonymous
|
EN
|
I consent
|
19
|
Female
|
50
|
50
|
77
|
60
|
25
|
20
|
13
|
|
|
|
|
|
|
|
0
|
1
|
1
|
8
|
50
|
20
|
6
|
5
|
4
|
5
|
5
|
6
|
5
|
6
|
Simple
|
2
|
10
|
8
|
|
27/9/20 23:18
|
IP Address
|
58.179.100.109
|
100
|
949
|
subj4
|
27/9/20 23:18
|
R_3enxzUsEYgs5r1a
|
-12.63921
|
141.8741
|
anonymous
|
EN
|
I consent
|
27
|
Female
|
|
|
|
|
|
|
|
70
|
80
|
90
|
95
|
70
|
80
|
90
|
1
|
1
|
1
|
8
|
50
|
20
|
6
|
6
|
6
|
1
|
6
|
6
|
6
|
1
|
Complex
|
3
|
8
|
7
|
|
28/9/20 0:45
|
IP Address
|
120.154.53.68
|
100
|
1097
|
subj5
|
28/9/20 0:45
|
R_2Qzl2096a4KNE29
|
-33.85910
|
151.2002
|
anonymous
|
EN
|
I consent
|
19
|
Male
|
71
|
73
|
85
|
95
|
95
|
32
|
32
|
|
|
|
|
|
|
|
1
|
1
|
1
|
4
|
10
|
39
|
6
|
6
|
5
|
5
|
6
|
6
|
6
|
6
|
Simple
|
3
|
11
|
11
|
|
28/9/20 2:20
|
IP Address
|
1.129.107.6
|
100
|
880
|
subj6
|
28/9/20 2:20
|
R_esb71WOTQySjusF
|
-33.85910
|
151.2002
|
anonymous
|
EN
|
I consent
|
20
|
Female
|
|
|
|
|
|
|
|
89
|
100
|
44
|
55
|
100
|
50
|
55
|
1
|
1
|
1
|
8
|
50
|
20
|
6
|
6
|
6
|
5
|
6
|
6
|
6
|
6
|
Complex
|
3
|
10
|
10
|
Now, let’s do some cleanining using dplyr, tidyr and other tidyverse libraries. Finally, we will check the data:
cleaned_data <- raw_data %>%
filter(progress == 100) %>% # filter out unfinished participants
select(-end_date, -status,-ip_address, -duration_in_seconds, -recorded_date:-user_language) %>% #remove some useless columns
mutate(aote_total= aote1+aote2+aote3+aote4+aote5+aote6+aote7+aote8, # create a total score for our questionnaire
attentive= case_when(attention_correct >= 2~ 'Yes',T~ 'No')) %>%
mutate(crt1= case_when(crt1=='4'~ 1,T~0),
crt2= case_when(crt2=='10'~ 1,T~0),
crt3= case_when(crt3=='39'~ 1,T~0),
crt_total= crt1 + crt2 + crt3) %>%
select(-attention1:-aote8) %>%
pivot_longer(cols = c(stage1_simple:stage7_simple,stage1_complex:stage7_complex),names_to = 'stage',values_to = 'truth_estimate') %>% # make our dataframe long
#pivot_wider(names_from = stage, values_from= truth_estimate) # this code change our dataframe back to wide
filter(!is.na(truth_estimate)) %>% #remove rows with truth_estimate == NA
mutate(stage= gsub("_.*", "", stage)) %>%
rename(consent= consent_form) %>% # rename a column
#mutate_if(is.character, factor) %>%
mutate(subject= factor(subject), # convert all characters to factor
group = factor(group),
attentive = factor(attentive),
stage = factor(stage))
|
progress
|
subject
|
consent
|
age
|
gender
|
group
|
attention_correct
|
numeracy_total
|
mindware_total
|
aote_total
|
attentive
|
crt_total
|
stage
|
truth_estimate
|
|
100
|
subj1
|
I consent
|
18
|
Female
|
Complex
|
3
|
9
|
9
|
39
|
Yes
|
0
|
stage1
|
36
|
|
100
|
subj1
|
I consent
|
18
|
Female
|
Complex
|
3
|
9
|
9
|
39
|
Yes
|
0
|
stage2
|
70
|
|
100
|
subj1
|
I consent
|
18
|
Female
|
Complex
|
3
|
9
|
9
|
39
|
Yes
|
0
|
stage3
|
68
|
|
100
|
subj1
|
I consent
|
18
|
Female
|
Complex
|
3
|
9
|
9
|
39
|
Yes
|
0
|
stage4
|
54
|
|
100
|
subj1
|
I consent
|
18
|
Female
|
Complex
|
3
|
9
|
9
|
39
|
Yes
|
0
|
stage5
|
51
|
|
100
|
subj1
|
I consent
|
18
|
Female
|
Complex
|
3
|
9
|
9
|
39
|
Yes
|
0
|
stage6
|
43
|
Ok, now the data is clean and tidy which means:
- Each variable forms a column.
- Each observation forms a row.
- Each type of observational unit forms a table (Wickham, 2014).
Check the dataframe and all the data types:
str(cleaned_data)
## tibble [917 × 14] (S3: tbl_df/tbl/data.frame)
## $ progress : num [1:917] 100 100 100 100 100 100 100 100 100 100 ...
## $ subject : Factor w/ 131 levels "subj1","subj10",..: 1 1 1 1 1 1 1 45 45 45 ...
## $ consent : chr [1:917] "I consent" "I consent" "I consent" "I consent" ...
## $ age : num [1:917] 18 18 18 18 18 18 18 18 18 18 ...
## $ gender : chr [1:917] "Female" "Female" "Female" "Female" ...
## $ group : Factor w/ 2 levels "Complex","Simple": 1 1 1 1 1 1 1 2 2 2 ...
## $ attention_correct: num [1:917] 3 3 3 3 3 3 3 3 3 3 ...
## $ numeracy_total : num [1:917] 9 9 9 9 9 9 9 9 9 9 ...
## $ mindware_total : num [1:917] 9 9 9 9 9 9 9 10 10 10 ...
## $ aote_total : num [1:917] 39 39 39 39 39 39 39 46 46 46 ...
## $ attentive : Factor w/ 2 levels "No","Yes": 2 2 2 2 2 2 2 2 2 2 ...
## $ crt_total : num [1:917] 0 0 0 0 0 0 0 2 2 2 ...
## $ stage : Factor w/ 7 levels "stage1","stage2",..: 1 2 3 4 5 6 7 1 2 3 ...
## $ truth_estimate : num [1:917] 36 70 68 54 51 43 41 50 55 55 ...
Finally, we save our data to the cleaned_data folder.
write_csv(cleaned_data, here("cleaned_data","argumentative_exp1.csv"))
Descriptive Statistics
Note: All the data that we use here is manipulated (fabricated) for teaching purpuses. In our study, we failed to find such beautiful and interesting results.
Now, let’s do some descriptive statistics. First, we can open a new script called analysis_exp1.r and read the cleaned data again.
data_exp1 <- read_csv(here("cleaned_data","argumentative_exp1.csv"))
How many participants in total?
data_exp1 %>% summarise(n= n_distinct(subject))
how many participants in each group?
data_exp1 %>%
group_by(subject) %>%
filter(row_number()==1) %>%
ungroup () %>%
group_by(group) %>%
count()
|
group
|
n
|
|
Complex
|
65
|
|
Simple
|
66
|
Find the mean and sd for numeric variables using base R summary function:
data_exp1 %>%
group_by(subject) %>%
filter(row_number()==1) %>%
ungroup () %>%
summary()
## progress subject consent age
## Min. :100 Length:131 Length:131 Min. :16.00
## 1st Qu.:100 Class :character Class :character 1st Qu.:18.00
## Median :100 Mode :character Mode :character Median :19.00
## Mean :100 Mean :21.15
## 3rd Qu.:100 3rd Qu.:20.00
## Max. :100 Max. :63.00
## gender group attention_correct numeracy_total
## Length:131 Length:131 Min. :0.000 Min. : 0.000
## Class :character Class :character 1st Qu.:2.000 1st Qu.: 8.000
## Mode :character Mode :character Median :3.000 Median :10.000
## Mean :2.573 Mean : 8.779
## 3rd Qu.:3.000 3rd Qu.:10.000
## Max. :3.000 Max. :11.000
## mindware_total aote_total attentive crt_total
## Min. : 4.00 Min. :19.0 Length:131 Min. :0.0000
## 1st Qu.: 8.00 1st Qu.:33.5 Class :character 1st Qu.:0.0000
## Median : 8.00 Median :39.0 Mode :character Median :0.0000
## Mean : 8.45 Mean :38.2 Mean :0.8092
## 3rd Qu.: 9.00 3rd Qu.:43.0 3rd Qu.:1.0000
## Max. :12.00 Max. :48.0 Max. :3.0000
## stage truth_estimate
## Length:131 Min. : 0.00
## Class :character 1st Qu.: 43.50
## Mode :character Median : 61.00
## Mean : 57.09
## 3rd Qu.: 75.50
## Max. :100.00
Alternatively, we can use base Rsummaryfunctionskimr` library:
data_exp1 %>%
group_by(subject) %>%
filter(row_number()==1) %>%
ungroup () %>%
dplyr::select (age, numeracy_total, mindware_total, aote_total, crt_total) %>%
skimr::skim()
|
skim_type
|
skim_variable
|
n_missing
|
complete_rate
|
numeric.mean
|
numeric.sd
|
numeric.p0
|
numeric.p25
|
numeric.p50
|
numeric.p75
|
numeric.p100
|
numeric.hist
|
|
numeric
|
age
|
0
|
1
|
21.1526718
|
6.515630
|
16
|
18.0
|
19
|
20
|
63
|
▇▁▁▁▁
|
|
numeric
|
numeracy_total
|
0
|
1
|
8.7786260
|
2.274576
|
0
|
8.0
|
10
|
10
|
11
|
▁▁▁▂▇
|
|
numeric
|
mindware_total
|
0
|
1
|
8.4503817
|
1.683466
|
4
|
8.0
|
8
|
9
|
12
|
▁▅▇▆▃
|
|
numeric
|
aote_total
|
0
|
1
|
38.1984733
|
6.153698
|
19
|
33.5
|
39
|
43
|
48
|
▁▂▇▇▆
|
|
numeric
|
crt_total
|
0
|
1
|
0.8091603
|
1.038598
|
0
|
0.0
|
0
|
1
|
3
|
▇▃▁▂▂
|
Exercise
For this exercise, we use a dataset of one of my own studies. In this study, we asked participants to guess the physical brightness of reasoning arguments and then we gave a cognitive ability test. (See the original study here). Open ghasemi_brightness_exp4.csv file and answer to the following questions:
- How many participants did we test in total?
- Find out how many male and female we tested.
- Calculate mean and sd for age and cognitive ability (
ah4).
ghasemi_data <- read_csv(here("cleaned_data","ghasemi_brightness_exp4.csv"))
ghasemi_data %>% summarise(n = n_distinct(participant)) # number of participants:200
ghasemi_data %>% group_by (participant) %>% filter (row_number()==1) %>% group_by (gender) %>% summarise(n= n()) %>% ungroup() # 183 female, 17 male
|
gender
|
n
|
|
Female
|
183
|
|
Male
|
17
|
ghasemi_data %>% dplyr::select (age, ah4) %>% skimr::skim() # mean and sd for age and cognitive ability
Data summary
|
|
|
|
Name
|
Piped data
|
|
Number of rows
|
38400
|
|
Number of columns
|
2
|
|
_______________________
|
|
|
Column type frequency:
|
|
|
numeric
|
2
|
|
________________________
|
|
|
Group variables
|
|
Variable type: numeric
|
skim_variable
|
n_missing
|
complete_rate
|
mean
|
sd
|
p0
|
p25
|
p50
|
p75
|
p100
|
hist
|
|
age
|
0
|
1
|
22.20
|
6.78
|
17
|
19
|
20
|
22
|
52
|
▇▁▁▁▁
|
|
ah4
|
0
|
1
|
39.55
|
9.46
|
11
|
34
|
40
|
46
|
61
|
▁▃▇▆▂
|
Data Visualization
First, we need to create a dataset with aggregated truth estimate scores over group and stage. We will use this dataset for line and bar graphs.
aggregated_data_exp1 <- data_exp1 %>%
group_by(stage, group) %>%
mutate(truth_estimate = mean(truth_estimate)) %>%
ungroup()
barplot_exp1 <- aggregated_data_exp1 %>%
ggplot(aes(x=stage, y= truth_estimate, fill=group)) +
geom_bar(stat = "identity", position= "dodge")+
# stat_summary(fun= mean, geom = "bar", position = "dodge")+ # can be used instead of geom_bar() for long dataframes
labs (x= '', y= "Truth Likelihhod Estimate") +
theme_bw() +
scale_fill_jama()
barplot_exp1

barplot_facet_exp1 <- aggregated_data_exp1 %>%
ggplot(aes(x=group, y= truth_estimate, fill=stage)) +
geom_bar(stat = "identity", position= "dodge")+
labs (x= '', y= "Truth Likelihhod Estimate") +
theme_bw() +
theme(legend.position = "none",
axis.text=element_text(size=11),
axis.title = element_text(size = 12)) +
facet_wrap(~stage)+
scale_fill_jco()
barplot_facet_exp1

lineplot_exp1 <- aggregated_data_exp1 %>%
ggplot(aes(x=factor(stage), y= truth_estimate, group= group, color= group)) +
geom_line(aes(linetype= group)) +
geom_point(size= 5)+
labs (x= '', y= "Truth Likelihhod Estimate") +
theme_classic() +
theme(legend.position = "bottom",
axis.text=element_text(size=11),
axis.title = element_text(size = 12)) +
scale_color_nejm()
lineplot_exp1

violinplot_exp1 <- data_exp1 %>%
ggplot(aes(x=factor(stage), y= truth_estimate, fill= group)) +
geom_violin()+
labs (x= '', y= "Truth Likelihhod Estimate") +
theme_bw() +
theme(legend.position = "bottom",
axis.text=element_text(size=11),
axis.title = element_text(size = 12)) +
scale_fill_d3()
violinplot_exp1

boxplot_exp1 <- data_exp1 %>%
ggplot(aes(x=factor(stage), y= truth_estimate, fill= group)) +
geom_boxplot()+
#geom_point(position = position_dodge(width=0.75), alpha= .5)+
labs (x= '', y= "Truth Likelihhod Estimate") +
theme_bw() +
theme(legend.position = "bottom",
axis.text=element_text(size=11),
axis.title = element_text(size = 12)) +
scale_fill_simpsons()
boxplot_exp1

boxplot_facet_exp1 <- data_exp1 %>%
ggplot(aes(x=factor(stage), y= truth_estimate, fill= group)) +
geom_boxplot()+
labs (x= '', y= "Truth Likelihhod Estimate") +
theme_bw() +
theme(legend.position = "bottom",
axis.text=element_text(size=11),
axis.title = element_text(size = 12),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
facet_wrap(~group)+
scale_color_simpsons()
boxplot_facet_exp1

How to combine multiple plots? We can use the patchwork package. A nice tutorial on using this package can be found here
combined_plot_exp1 <- (barplot_facet_exp1+lineplot_exp1) / (violinplot_exp1+boxplot_exp1)
combined_plot_exp1

How to save a plot?
ggsave(combined_plot_exp1, filename = here("outputs","combined_plot_exp1.png"), dpi=300)
Data Analysis
t-test
Is there a difference between groups at the first stage? Ideally, we want participants’ ratings at the first stage be similar for both groups because we have not done any manipulations. Previous graphs showed us that ratings of simple and complex group at this stage are pretty close. Let’s test that using an independent t-test (because we have 2 independent groups):
# Is there a difference between groups at the first stage?
data_exp1 %>%
group_by(group) %>%
filter(stage=='stage1') %>%
ungroup () %>%
t.test(truth_estimate~group, data = ., paired=FALSE)
##
## Welch Two Sample t-test
##
## data: truth_estimate by group
## t = -0.75145, df = 104.95, p-value = 0.4541
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -11.883716 5.351781
## sample estimates:
## mean in group Complex mean in group Simple
## 55.44615 58.71212
Now, we wonder if opposing arguments were effective at all, regardless of participants’ group. So, we would like to test if ratings at the final stage are lower than ratings at the stage 4? Since a pair of score at stage 4 and stage 7 is coming from a same person, we use paired t-test.
# Is there a difference between ratings of stage4 and stage7?
data_exp1 %>%
filter(stage=='stage4' | stage=='stage7') %>%
ungroup () %>%
t.test(truth_estimate~stage, data = ., paired=TRUE)
##
## Paired t-test
##
## data: truth_estimate by stage
## t = 12.788, df = 130, p-value < 0.00000000000000022
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## 32.64368 44.59296
## sample estimates:
## mean of the differences
## 38.61832
Exercise
John et al. (2019) investigated the consequences of backing down (changing one’s mind in lights of evidence)and how other people view someone who change their mind. In their second experiments, they presented participants either with a person who changes their mind or a person who refuses to back down. Then, they asked participants to rate how intelligent and confident the person is (See the original study here). They reported that:
“Relative to the entrepreneur who did not back down, participants judged the entrepreneur who backed down as more intelligent (M_backed_down=5.13 out of 7, SD=1.09; M_did_not_back_down=3.97, SD=1.54; t(271.12)=−7.59, p < .001) but less confident (M_backed_down=4.50 out of 7, SD=1.36; M_did_not_back_down=5.65, SD=1.10; t(291.01)=8.08, p < .001).”.
Open the john_backdown_exp2.csv file and try to reproduce their results. Run two separate independent t-test, one with intelligent as the dependent variable and one with confident as the dependent variable. For both t-test, use back_down as the between-subject independent variable.
john_data <- read_csv(here("cleaned_data","john_backdown_exp2.csv"))
t.test(intelligent~back_down, data = john_data, paired=FALSE)
##
## Welch Two Sample t-test
##
## data: intelligent by back_down
## t = 7.5853, df = 271.12, p-value = 0.0000000000005319
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## 0.8577107 1.4590076
## sample estimates:
## mean in group backed_down mean in group did_not_back_down
## 5.129412 3.971053
t.test(confident~back_down, data = john_data, paired=FALSE)
##
## Welch Two Sample t-test
##
## data: confident by back_down
## t = -8.0763, df = 291.01, p-value = 0.00000000000001787
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -1.4257768 -0.8670294
## sample estimates:
## mean in group backed_down mean in group did_not_back_down
## 4.503268 5.649671
Analysis of Variance (ANOVA)
Now, let’s answer our main question: Do participants in the simple group show higher ratings for supportive arguments (stage 2 to 4) and lower ratings for opposing arguments (stage 5 to 7), compared to participants in the complex group? If this is the case. we expect an interaction in the traditional Analysis of Variance (AONVA) test.
aov_m1 <- aov_car (truth_estimate ~ group*stage +
Error(subject/stage), data = data_exp1)
|
Effect
|
df
|
MSE
|
F
|
ges
|
p.value
|
|
group
|
1, 129
|
949.04
|
0.01
|
<.0001
|
.94
|
|
stage
|
4.45, 574.05
|
515.69
|
59.48 ***
|
.25
|
<.0001
|
|
group:stage
|
4.45, 574.05
|
515.69
|
13.34 ***
|
.07
|
<.0001
|
As you can see, we found a significant main effect of stage and a significant group by stage interaction. We can use the emmeans package to do post-hoc tests.
# main effect of stage
emmeans(aov_m1, 'stage')
## stage emmean SE df lower.CL upper.CL
## stage1 57.1 1.88 763 53.4 60.8
## stage2 66.8 1.88 763 63.1 70.5
## stage3 74.6 1.88 763 70.9 78.3
## stage4 79.6 1.88 763 75.9 83.3
## stage5 62.4 1.88 763 58.7 66.1
## stage6 52.5 1.88 763 48.9 56.2
## stage7 41.1 1.88 763 37.4 44.8
##
## Results are averaged over the levels of: group
## Warning: EMMs are biased unless design is perfectly balanced
## Confidence level used: 0.95
pairs(emmeans(aov_m1, 'stage'), adjust= 'holm')
## contrast estimate SE df t.ratio p.value
## stage1 - stage2 -9.74 2.42 774 -4.031 0.0004
## stage1 - stage3 -17.53 2.42 774 -7.256 <.0001
## stage1 - stage4 -22.50 2.42 774 -9.311 <.0001
## stage1 - stage5 -5.29 2.42 774 -2.187 0.1160
## stage1 - stage6 4.53 2.42 774 1.876 0.1220
## stage1 - stage7 15.98 2.42 774 6.613 <.0001
## stage2 - stage3 -7.79 2.42 774 -3.225 0.0066
## stage2 - stage4 -12.76 2.42 774 -5.280 <.0001
## stage2 - stage5 4.46 2.42 774 1.844 0.1220
## stage2 - stage6 14.28 2.42 774 5.908 <.0001
## stage2 - stage7 25.72 2.42 774 10.644 <.0001
## stage3 - stage4 -4.97 2.42 774 -2.055 0.1206
## stage3 - stage5 12.25 2.42 774 5.069 <.0001
## stage3 - stage6 22.07 2.42 774 9.132 <.0001
## stage3 - stage7 33.51 2.42 774 13.869 <.0001
## stage4 - stage5 17.22 2.42 774 7.124 <.0001
## stage4 - stage6 27.04 2.42 774 11.188 <.0001
## stage4 - stage7 38.48 2.42 774 15.924 <.0001
## stage5 - stage6 9.82 2.42 774 4.064 0.0004
## stage5 - stage7 21.27 2.42 774 8.800 <.0001
## stage6 - stage7 11.45 2.42 774 4.736 <.0001
##
## Results are averaged over the levels of: group
## P value adjustment: holm method for 21 tests
# group by stage interaction
emmeans(aov_m1, "group", by= "stage")
## stage = stage1:
## group emmean SE df lower.CL upper.CL
## Complex 55.4 2.67 766 50.2 60.7
## Simple 58.7 2.65 761 53.5 63.9
##
## stage = stage2:
## group emmean SE df lower.CL upper.CL
## Complex 63.3 2.67 766 58.1 68.6
## Simple 70.3 2.65 761 65.1 75.5
##
## stage = stage3:
## group emmean SE df lower.CL upper.CL
## Complex 70.0 2.67 766 64.7 75.2
## Simple 79.3 2.65 761 74.1 84.5
##
## stage = stage4:
## group emmean SE df lower.CL upper.CL
## Complex 71.6 2.67 766 66.3 76.8
## Simple 87.6 2.65 761 82.4 92.8
##
## stage = stage5:
## group emmean SE df lower.CL upper.CL
## Complex 64.2 2.67 766 58.9 69.4
## Simple 60.5 2.65 761 55.3 65.8
##
## stage = stage6:
## group emmean SE df lower.CL upper.CL
## Complex 57.9 2.67 766 52.7 63.2
## Simple 47.2 2.65 761 41.9 52.4
##
## stage = stage7:
## group emmean SE df lower.CL upper.CL
## Complex 51.1 2.67 766 45.9 56.4
## Simple 31.1 2.65 761 25.9 36.3
##
## Warning: EMMs are biased unless design is perfectly balanced
## Confidence level used: 0.95
update(pairs(emmeans(aov_m1, "group", by= "stage")), by = NULL, adjust = "holm")
## contrast stage estimate SE df t.ratio p.value
## Complex - Simple stage1 -3.27 3.76 763 -0.868 0.6673
## Complex - Simple stage2 -6.96 3.76 763 -1.851 0.1935
## Complex - Simple stage3 -9.29 3.76 763 -2.469 0.0550
## Complex - Simple stage4 -16.02 3.76 763 -4.259 0.0001
## Complex - Simple stage5 3.64 3.76 763 0.967 0.6673
## Complex - Simple stage6 10.79 3.76 763 2.868 0.0213
## Complex - Simple stage7 20.08 3.76 763 5.337 <.0001
##
## P value adjustment: holm method for 7 tests
You can use the afex_plot function from afex to create beautiful plots. Those plots interacts nicely with ggplot:
afex_plot(aov_m1, x = "stage", trace = "group", error='between',
line_arg = list(size=1),
point_arg = list(size=3.5),
data_arg = list(size= 1, color= 'grey', width=.4),
data_geom = geom_boxplot,
mapping = c("linetype", "shape", "fill"),
legend_title = "Group") +
labs(y = "Truth Likelihhod Estimate", x = "") +
theme_bw()+ # remove the grey background and grid
theme(axis.text=element_text(size=13),
axis.title = element_text(size = 13),
legend.text=element_text(size=13),
legend.title=element_text(size=13),
legend.position='bottom',
legend.key.size = unit(1, "cm"),
legend.background = element_rect(colour = 'black', fill = 'white', linetype='solid'))+
scale_color_simpsons() +
scale_fill_simpsons()

If you are interested in this topic, check out this nice tutorial about using afex to run ANOVA, and also this interesting tutorial on the emmeans package.
Exercise
Rotello et al. (2018) investigated the association between the race (White vs. Black faces) and the gun-tool judgments. In their first experiments, they presented participants with 16 White male faces and 16 Black male faces, and following that 8 images of guns and 8 images of tools. They asked participants to judge if the object is a tool or a gun by pressing keyboard buttons. Then, they ran an ANOVA to see if participants’ gun responses are higher for any of the races. So, they included prime race (Black, White) and target identity (gun, tool) as independent variables and participants’ gun responses as dependent variable into their linear model (See the original study here). They found that:
“Participants made more gun responses to guns than to tools, F(1,45) = 53243, p < 0.0001, η2g = 0.998. However, the race of the prime face did not matter, F(1,45) = 0.287, p > 0.59, η2g = 0.001, nor was there an interaction of prime race with target object, F(1,45) = 0.022, p > 0.88, η2g = 0.000)”.
Open the rotello_shooter_exp1.csv file and try to reproduce their results. Run an ANOVA (type III) with resp as the dependent variable and target, prime, and their interaction as independent variables.
# load the general data file
rotello_data <- read_csv(here("cleaned_data","rotello_shooter_exp1.csv"))
# ANOVA
rotello_aov <- aov_car (resp ~ target*prime +
Error(subject/target*prime), data = rotello_data)
|
Effect
|
df
|
MSE
|
F
|
ges
|
p.value
|
|
target
|
1, 45
|
0.00
|
53242.99 ***
|
>.99
|
<.0001
|
|
prime
|
1, 45
|
0.00
|
0.29
|
.001
|
.59
|
|
target:prime
|
1, 45
|
0.00
|
0.02
|
<.0001
|
.88
|
Correlation
Now, let’s answer to another question of this study: does persuasion and dissuasion is related to open-mindedness, cognitive ability, reasoning abilities, and cognitive style? To answer this question, we need to create two indexes (scores) one for persuasion and one for dissuasion. Then we can do a correlation test:
cor_data_exp1 <- data_exp1 %>%
pivot_wider(names_from = stage, values_from = truth_estimate) %>%
group_by(subject) %>%
mutate(persuasion_index= stage2+ stage3+ stage4 - stage1,
dissuasion_index= (101-stage5) + (101-stage6) + (101-stage7) - (101-stage4)) %>%
ungroup()%>%
dplyr::select(persuasion_index,dissuasion_index,aote_total,numeracy_total,crt_total,mindware_total)
#---------- Base R:
cor(cor_data_exp1, method = "pearson", use = "complete.obs")
#---------- Psych library:
cor_data_exp1 %>%
psych::pairs.panels(method = "pearson", hist.col = "#00AFBB", density = T, ellipses = F, stars = T)
#---------- Correlation library:
correlation::correlation(cor_data_exp1) %>% summary()
#---------- apaTables library:
cor_data_exp1 %>%
apaTables::apa.cor.table(filename="./outputs/CorMatrix.doc", show.conf.interval=T)
|
|
persuasion_index
|
dissuasion_index
|
aote_total
|
numeracy_total
|
crt_total
|
mindware_total
|
|
persuasion_index
|
1.00
|
0.26
|
0.25
|
0.16
|
0.16
|
0.11
|
|
dissuasion_index
|
0.26
|
1.00
|
-0.03
|
-0.03
|
-0.09
|
0.15
|
|
aote_total
|
0.25
|
-0.03
|
1.00
|
0.40
|
0.26
|
0.11
|
|
numeracy_total
|
0.16
|
-0.03
|
0.40
|
1.00
|
0.44
|
0.15
|
|
crt_total
|
0.16
|
-0.09
|
0.26
|
0.44
|
1.00
|
0.29
|
|
mindware_total
|
0.11
|
0.15
|
0.11
|
0.15
|
0.29
|
1.00
|
|
Parameter
|
mindware_total
|
crt_total
|
numeracy_total
|
aote_total
|
dissuasion_index
|
|
persuasion_index
|
0.11
|
0.16
|
0.16
|
0.25
|
0.26
|
|
dissuasion_index
|
0.15
|
-0.09
|
-0.03
|
-0.03
|
|
|
aote_total
|
0.11
|
0.26
|
0.40
|
|
|
|
numeracy_total
|
0.15
|
0.44
|
|
|
|
|
crt_total
|
0.29
|
|
|
|
|
Exercise
Pennycook et al. (2020) investigated the relationship between actively open-minded thinking style about evidence (AOT-E) and different political, scientific, and religious beliefs (see the original paper here). In their first experiment, they calculated the correlation of AOTE and scientific beliefs items (global warming, evolution, etc.) and they found the following results:
Open the pennycook_aote_exp1.csv file and try to reproduce their results by creating the same correlation matrix.
pennycook_data <- read_csv(here("cleaned_data","pennycook_aote_exp1.csv"))
#---------- Base R:
cor(pennycook_data, method = "pearson", use = "complete.obs")
#---------- Psych library:
pennycook_data %>%
psych::pairs.panels(method = "pearson", hist.col = "#00AFBB", density = T, ellipses = F, stars = T)
#---------- Correlation library:
correlation::correlation(pennycook_data) %>% summary()
#---------- apaTables library:
pennycook_data %>%
apaTables::apa.cor.table(filename="./outputs/CorMatrix.doc", show.conf.interval=T)
|
Parameter
|
trust_scien
|
gm_health
|
tech_problems
|
modern_medicine
|
old_earth
|
vaccines
|
stem_cell
|
big_bang
|
evolution
|
global_warming
|
|
aote
|
0.35
|
0.36
|
0.44
|
0.33
|
0.40
|
0.47
|
0.45
|
0.51
|
0.51
|
0.37
|
|
global_warming
|
0.42
|
0.06
|
0.14
|
0.18
|
0.33
|
0.26
|
0.31
|
0.33
|
0.38
|
|
|
evolution
|
0.48
|
0.33
|
0.28
|
0.36
|
0.47
|
0.39
|
0.54
|
0.78
|
|
|
|
big_bang
|
0.49
|
0.37
|
0.28
|
0.36
|
0.45
|
0.37
|
0.54
|
|
|
|
|
stem_cell
|
0.47
|
0.34
|
0.36
|
0.47
|
0.40
|
0.40
|
|
|
|
|
|
vaccines
|
0.43
|
0.52
|
0.49
|
0.53
|
0.38
|
|
|
|
|
|
|
old_earth
|
0.29
|
0.24
|
0.21
|
0.33
|
|
|
|
|
|
|
|
modern_medicine
|
0.43
|
0.42
|
0.47
|
|
|
|
|
|
|
|
|
tech_problems
|
0.33
|
0.39
|
|
|
|
|
|
|
|
|
|
gm_health
|
0.31
|
|
|
|
|
|
|
|
|
|
Linear Regression
In the previous section, we found that open-mindedness (AOT-E) is correlated with persuasion. Now, one may ask if open-mindedness can predict persuasion after controlling for reasoning and controlling abilities? To answer that, we can run a multiple regression analysis:
exp1_reg=lm(persuasion_index ~ aote_total+ numeracy_total+ crt_total+ mindware_total,
data=cor_data_exp1)
|
term
|
estimate
|
std.error
|
statistic
|
p.value
|
|
(Intercept)
|
78.57
|
33.08
|
2.38
|
0.02
|
|
aote_total
|
1.62
|
0.72
|
2.23
|
0.03
|
|
numeracy_total
|
0.72
|
2.11
|
0.34
|
0.73
|
|
crt_total
|
3.09
|
4.51
|
0.68
|
0.49
|
|
mindware_total
|
1.77
|
2.52
|
0.70
|
0.48
|
Exercise
Trémolière and Djeriouat (2020) examined the role of cognitive reflection and belief in science in climate change skepticism. In their first study, they revealed that cognitive reflection and belief in science negetively predicted climate change skepticism even after controlling for demographic and cognitive ability variables (see the original paper here).
Open the tremoliere_data_exp1.csv file and try to reproduce their results by running a multiple linear regression. Enter age, gender, education, belief in science, literacy, numeracy (Numtotal), and cognitive reflection as predictors and enter climate change skepticism (climato) as the outcome variable.
Tremoliere_data <- read_csv(here("cleaned_data","tremoliere_data_exp1.csv"))
Tremoliere_reg=lm(Climato ~ Age+ Gender+ Education+ BeliefInSciencetotal+ Literacy+ Numtotal+ CognitiveReflection,
data=Tremoliere_data)
|
term
|
estimate
|
std.error
|
statistic
|
p.value
|
|
(Intercept)
|
57.57
|
5.19
|
11.09
|
0.00
|
|
Age
|
0.01
|
0.05
|
0.24
|
0.81
|
|
Gender
|
-5.68
|
1.34
|
-4.23
|
0.00
|
|
Education
|
0.54
|
0.38
|
1.43
|
0.15
|
|
BeliefInSciencetotal
|
-0.20
|
0.06
|
-3.62
|
0.00
|
|
Literacy
|
-0.49
|
0.51
|
-0.96
|
0.34
|
|
Numtotal
|
-1.52
|
0.83
|
-1.82
|
0.07
|
|
CognitiveReflection
|
-18.58
|
4.26
|
-4.37
|
0.00
|
|
r.squared
|
adj.r.squared
|
sigma
|
statistic
|
p.value
|
df
|
logLik
|
AIC
|
BIC
|
deviance
|
df.residual
|
nobs
|
|
0.19
|
0.17
|
12.65
|
11.91
|
0
|
7
|
-1467.77
|
2953.54
|
2988.81
|
58235.89
|
364
|
372
|
Rmarkdown
To be completed…
References
Ghasemi, O., Handley, S., & Howarth, S. (2020). The Bright Homunculus in our Head: Individual Differences in Intuitive Sensitivity to Logical Validity.
John, L. K., Jeong, M., Gino, F., & Huang, L. (2019). The self-presentational consequences of upholding one’s stance in spite of the evidence. Organizational Behavior and Human Decision Processes, 154, 1-14.
Pennycook, G., Cheyne, J. A., Koehler, D. J., & Fugelsang, J. A. (2020). On the belief that beliefs should change according to evidence: Implications for conspiratorial, moral, paranormal, political, religious, and science beliefs. Judgment and Decision Making, 15(4), 476.
Rotello, C. M., Kelly, L. J., Heit, E., Vazire, S., & Vul, E. (2018). The Shape of ROC Curves in Shooter Tasks: Implications for Best Practices in Analysis. Collabra: Psychology, 4(1).
Trémolière, B., & Djeriouat, H. (2020). Don’t you see that its cold! Exploring the roles of cognitive reflection, climate science literacy, illusion of knowledge, and political orientation in climate change skepticism.
Wickham, H. (2014). Tidy data. Journal of Statistical Software, 59(10), 1-23.
LS0tCnRpdGxlOiAiUiBmb3IgQ29nbml0aXZlIFBzeWNob2xvZ2lzdHMiCmF1dGhvcjoKICAtIG5hbWU6ICJPbWlkIEdoYXNlbWkiCiAgICBhZmZpbGlhdGlvbjogTWFjcXVhcmllIFVuaXZlcnNpdHkKICAgIGVtYWlsOiBvbWlkcmV6YS5naGFzZW1pQGhkci5tcS5lZHUuYXUKICAtIG5hbWU6ICJNYWhkaSBNYXppZGkiCiAgICBhZmZpbGlhdGlvbjogVW5pdmVyc2l0eSBvZiBXZXN0ZXJuIEF1c3RyYWxpYQogICAgZW1haWw6IG1haGRpLm1hemlkaXNoYXJhZmFiYWRpQHJlc2VhcmNoLnV3YS5lZHUuYXUKZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJUIsICVZJylgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICBrZWVwX21kOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgdGhlbWU6IGNlcnVsZWFuCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAjY29kZV9mb2xkaW5nOiBoaWRlCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgZGZfcHJpbnQ6ICJrYWJsZSIKLS0tCgpUaGlzIGRvY3VtZW50IGlzIHRoZSBzdW1tYXJ5IG9mIHRoZSAqKlIgZm9yIENvZ25pdGl2ZSBQc3ljaG9sb2dpc3RzKiogd29ya3Nob3AuIAoKQWxsIGNvcnJlc3BvbmRlbmNlIHJlbGF0ZWQgdG8gdGhpcyBkb2N1bWVudCBzaG91bGQgYmUgYWRkcmVzc2VkIHRvOiAKCjxjZW50ZXI+Ck9taWQgR2hhc2VtaSAoTWFjcXVhcmllIFVuaXZlcnNpdHksIFN5ZG5leSwgTlNXLCAyMTA5LCBBVVNUUkFMSUEpIAoKRW1haWw6IG9taWRyZXphLmdoYXNlbWlAaGRyLm1xLmVkdS5hdSAKPC9jZW50ZXI+CgoKCjxzdHlsZT4KCmJvZHl7IC8qIE5vcm1hbCAgKi8KICAgICAgZm9udC1zaXplOiAxOHB4OwogICAgICB0ZXh0LWFsaWduOiBqdXN0aWZ5OwogICAgICBsaW5lLWhlaWdodDogMS42OwogICAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKfQpjb2RlLnJ7IC8qIENvZGUgYmxvY2sgKi8KICAgIGZvbnQtc2l6ZTogMTRweDsKfQpwcmUgeyAvKiBDb2RlIGJsb2NrIC0gZGV0ZXJtaW5lcyBjb2RlIHNwYWNpbmcgYmV0d2VlbiBsaW5lcyAqLwogICAgZm9udC1zaXplOiAxMnB4Owp9Cgo8L3N0eWxlPgoKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcuYWxpZ249ImNlbnRlciIpCmBgYAoKCgpgYGB7ciBsaWJyYXJpZXMsIG1lc3NhZ2U9RkFMU0UsIGVjaG89Rn0KIyBsb2FkIGxpYnJhcmllcwpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShoZXJlKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoYnJvb20pCmxpYnJhcnkoYWZleCkKbGlicmFyeShlbW1lYW5zKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkoZ2dzY2kpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KHNraW1yKQojIGluc3RhbGwucGFja2FnZXMoImRldnRvb2xzIikKIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImVhc3lzdGF0cy9jb3JyZWxhdGlvbiIpCmxpYnJhcnkoImNvcnJlbGF0aW9uIikKb3B0aW9ucyhzY2lwZW49OTk5KSAjIHR1cm4gb2ZmIHNjaWVudGlmaWMgbm90YXRpb25zCm9wdGlvbnMoY29udHJhc3RzID0gYygnY29udHIuc3VtJywnY29udHIucG9seScpKSAjIHNldCB0aGUgY29udHJhc3Qgc3VtIGdsb2JhbGx5IApvcHRpb25zKGtuaXRyLmthYmxlLk5BID0gJycpCmBgYAoKCiMgUmVzZWFyY2ggUXVlc3Rpb24KCgpUaGUgYWltIG9mIHRoZSBzdHVkeSBpcyB0byB0ZXN0IGlmIHNpbXBsZSBhcmd1bWVudHMgYXJlIG1vcmUgZWZmZWN0aXZlIGluIGJlbGllZiByZXZpc2lvbiB0aGFuIG1vcmUgY29tcGxleCBhcmd1bWVudHMuIFRvIHRoYXQgZW5kLCB3ZSBwcmVzZW50IHBhcnRpY2lwYW50cyB3aXRoIGFuIGltYWdpbmFyeSBzY2VuYXJpbyAodHdvIGFsaWVuIGNyZWF0dXJlcyBvbiBhIHBsYW5ldCkgYW5kIGEgdGhlb3J5IChvbmUgY3JlYXR1cmUgaXMgcHJlZGF0b3IgYW5kIHRoZSBvdGhlciBvbmUgaXMgcHJleSkgYW5kIHdlIGFzayB0aGVtIHRvIHJhdGUgdGhlIGxpa2VsaWhvb2QgdHJ1dGggb2YgdGhlIHRoZW9yeSBiYXNlZCBvbiBhIHNpbXBsZSBmYWN0IChXZSBhZGFwdGVkIHRoaXMgbWV0aG9kIGZyb20gR3JlZ2cgZXQgYWwuLDIwMTc7IHNlZSB0aGUgb3JpZ2luYWwgc3R1ZHkgW2hlcmVdKGh0dHBzOi8vam91cm5hbHMuc2FnZXB1Yi5jb20vZG9pLzEwLjEwODAvMTc0NzAyMTguMjAxNS4xMDk5MTYyKSkuIFRoZW4sIGluIGEgYmV0d2Vlbi1zdWJqZWN0IG1hbmlwdWxhdGlvbiwgcGFydGljaXBhbnRzIHdpbGwgYmUgcHJlc2VudGVkIHdpdGggZWl0aGVyIDYgc2ltcGxlIGFyZ3VtZW50cyAoTW9kdXMgUG9uZW5zIGNvbmRpdGlvbmFscykgb3IgNiBtb3JlIGNvbXBsZXggYXJndW1lbnRzIChNb2R1cyBUb2xsZW5zIGNvbmRpdGlvbmFscyksIGFuZCB0aGV5IHdpbGwgYmUgYXNrZWQgdG8gcmF0ZSB0aGUgbGlrZWxpaG9vZCB0cnV0aCBvZiB0aGUgaW5pdGlhbCB0aGVvcnkgb24gNyBzdGFnZXMuIAoKVGhlIGZpcnN0IHN0YWdlIGlzIHRoZSBiYXNlIHJhdGluZyBzdGFnZS4gVGhlIG5leHQgdGhyZWUgc3RhZ2VzIGluY2x1ZGUgc3VwcG9ydGl2ZSBhcmd1bWVudHMgb2YgdGhlIHRoZW9yeSBhbmQgdGhlIGxhc3QgdGhyZWUgYXJndW1lbnRzIGluY2x1ZGUgZGlzcHJvdmluZyBhcmd1bWVudHMgb2YgdGhlIHRoZW9yeS4gV2UgaHlwb3RoZXNpemVkIHRoYXQgdGhlIGdyb3VwIHdpdGggc2ltcGxlIGFyZ3VtZW50cyBzaG93cyBiZXR0ZXIgcGVyc3Vhc2lvbiAoYXMgaXQgcmVmbGVjdHMgaW4gaGlnaGVyIHJhdGluZ3MgZm9yIHRoZSBzdXBwb3J0aXZlIGFyZ3VtZW50cykgYW5kIGJldHRlciBkaXNzdWFzaW9uIChhcyBpdCByZWZsZWN0cyBpbiBsb3dlciByYXRpbmdzIGZvciB0aGUgb3Bwb3NpbmcgYXJndW1lbnRzKS4KCkluIHRoZSBsYXN0IHBhcnQgb2YgdGhlIHN0dWR5LCBwYXJ0aWNpcGFudHMgd2lsbCBiZSBhc2tlZCB0byBhbnN3ZXIgc2V2ZXJhbCBjb2duaXRpdmUgY2FwYWNpdHkvc3R5bGUgbWVhc3VyZXMgaW5jbHVkaW5nIENSVCwgQU9ULUUsIG1pbmR3YXJlLCBhbmQgbnVtZXJhY3kgc2NhbGVzLiBXZSBoeXBvdGhlc2l6ZWQgdGhhdCBjb2duaXRpdmUgYWJpbGl0eSwgY29nbml0aXZlIHN0eWxlLCBhbmQgb3Blbi1taW5kZWRuZXNzIGFyZSBwb3NpdGl2ZSBwcmVkaWN0b3JzIG9mIHBlcnN1YXNpb24gYW5kIGRpc3N1YXNpb24uIFRoZXNlIGFzc29jaWF0aW9ucyBzaG91bGQgYmUgbW9yZSBwcm9ub3VuY2VkIGZvciBwYXJ0aWNpcGFudHMgaW4gdGhlIGdyb3VwIHdpdGggY29tcGxleCBhcmd1bWVudHMgYmVjYXVzZSB0aGUgYWJpbGl0eSBhbmQgd2lsbGluZ25lc3MgdG8gZW5nYWdlIGluIGRlbGliZXJhdGl2ZSB0aGlua2luZyBtYXkgZmF2b3IgcGFydGljaXBhbnRzIHRvIGFzc2VzcyB0aGUgdW5kZXJseWluZyBsb2dpY2FsIHN0cnVjdHVyZSBvZiB0aG9zZSBhcmd1bWVudHMuIEhvd2V2ZXIsIGZvciBwYXJ0aWNpcGFudHMgaW4gdGhlIHNpbXBsZSBncm91cCwgdGhlIGxvZ2ljYWwgc3RydWN0dXJlIG9mIGFyZ3VtZW50cyBpcyBtb3JlIGV2aWRlbnQsIHNvIHBhcnRpY2lwYW50cyB3aXRoIGxvd2VyIGFiaWxpdHkgY2FuIHN0aWxsIGFzc2VzcyB0aGUgbG9naWNhbCBzdGF0dXMgb2YgdGhvc2UgYXJndW1lbnRzLgogCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGVjaG89RkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmUoJ2lucHV0cycsJ2V4cF9kZXNpZ24ucG5nJykpCmBgYAoKVGh1cywgb3VyIGh5cG90aGVzZXMgZm9yIHRoaXMgZXhwZXJpbWVudCBhcmUgYXMgZm9sbG93czoKCi0gUGFydGljaXBhbnRzIGluIHRoZSBncm91cCB3aXRoIHNpbXBsZSBhcmd1bWVudHMgaGF2ZSBoaWdoZXIgcmF0aW5ncyBmb3Igc3VwcG9ydGl2ZSBhcmd1bWVudHMgKFRoZXkgYXJlIG1vcmUgZWFzaWx5IHBlcnN1YWRlZCB0aGFuIHRob3NlIGluIHRoZSBncm91cCB3aXRoIGNvbXBsZXggYXJndW1lbnRzKS4KCi0gUGFydGljaXBhbnRzIGluIHRoZSBncm91cCB3aXRoIHNpbXBsZSBhcmd1bWVudHMgaGF2ZSBsb3dlciByYXRpbmdzIGZvciBvcHBvc2luZyBhcmd1bWVudHMgKFRoZXkgYXJlIG1vcmUgZWFzaWx5IGRpc3N1YWRlZCB0aGFuIHRob3NlIGluIHRoZSBncm91cCB3aXRoIGNvbXBsZXggYXJndW1lbnRzKS4KCi0gVGhlcmUgYXJlIHNpZ25pZmljYW50IGFzc29jaWF0aW9ucyBiZXR3ZWVuIENSVCwgQU9ULUUsIE51bWVyYWN5LCBhbmQgbWluZHdhcmUgd2l0aCBib3RoIHBlcnN1YXNpb24gYW5kIGRpc3N1YXNpb24gaW5kZXhlcyBpbiBlYWNoIGdyb3VwIGFuZCBpbiB0aGUgZW50aXJlIHNhbXBsZS4gVGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZXNlIG1lYXN1cmVzIHNob3VsZCBiZSBzdHJvbmdlciwgYWx0aG91Z2ggbm90IHNpZ25pZmljYW50bHksIGZvciBwYXJ0aWNpcGFudHMgaW4gdGhlIGdyb3VwIHdpdGggY29tcGxleCBhcmd1bWVudHMuCgoKYGBge3IgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI1NTBweCIsIG91dC5oZWlnaHQ9IjQwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZSgnaW5wdXRzJywncHJlZGljdGlvbl9wbG90LnBuZycpKQpgYGAKCgojIEdldHRpbmcgUmVhZHkKCkZpcnN0LCB3ZSBuZWVkIHRvIGRlc2lnbiB0aGUgZXhwZXJpbWVudC4gRm9yIHRoaXMgZXhwZXJpbWVudCwgd2UgdXNlIG9ubGluZSBwbGF0Zm9ybXMgZm9yIGRhdGEgY29sbGVjdGlvbi4gVGhlcmUgYXJlIHNldmVyYWwgb3B0aW9ucyBzdWNoIGFzIEdvcmlsbGEsIEpTcHN5Y2gsIFF1YWx0cmljcywgcHN5Y2hvSlMgKHBhdmxvdmlhKSwgZXRjLiBTaW5jZSB3ZSBkbyBub3QgbmVlZCBhbnkgcmVhY3Rpb24gdGltZSBkYXRhLCB3ZSBzaW1wbHkgdXNlIFF1YWx0cmljcy4gRm9yIGFuIG92ZXJ2aWV3IG9mIGRpZmZlcmVudCBsYWItYmFzZWQgYW5kIG9ubGluZSBwbGF0Zm9ybXMsIHNlZSBbaGVyZV0oaHR0cHM6Ly9vbWlkZ2hhc2VtaTIxLmdpdGh1Yi5pby9odW1hbl9kYXRhL1NjcmlwdHMvYmVoYXZpb3JhbF9kYXRhLmh0bWwpLiAKCk5leHQsIHdlIG5lZWQgdG8gZGVjaWRlIG9uIHRoZSBudW1iZXIgb2YgcGFydGljaXBhbnRzIChzYW1wbGUgc2l6ZSkuIEZvciB0aGlzIHN0dWR5LCB3ZSBkbyBub3Qgc3VlIHBvd2VyIGFuYWx5c2lzIHNpbmNlIHdlIGNhbm5vdCBhY2Nlc3MgbW9yZSB0aGFuIDEyMCBwYXJ0aWNpcGFudHMuIEhvd2V2ZXIsIGl0IGlzIGhpZ2hseSBzdWdnZXN0ZWQgY2FsY3VsYXRlIHNhbXBsZSBzaXplIHVzaW5nIHBvd2VyIGVzdGltYXRpb24uIFlvdSBjYW4gZmluZCBzb21lIG5pY2UgdHV0b3JpYWxzIG9uIGhvdyB0byBkbyB0aGF0IFtoZXJlXShodHRwczovL2p1bGlhbnF1YW5kdC5jb20vcG9zdC9wb3dlci1hbmFseXNpcy1ieS1kYXRhLXNpbXVsYXRpb24taW4tci1wYXJ0LWkvKSwgW2hlcmVdKGh0dHBzOi8vbmlja2NoLWsuZ2l0aHViLmlvL0Vjb25vbWV0cmljc1NsaWRlcy9XZWVrXzA4L1Bvd2VyX1NpbXVsYXRpb25zLmh0bWwpLCBhbmQgW2hlcmVdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9wYXJhbXRlc3QvdmlnbmV0dGVzL1NpbXVsYXRpbmctUG93ZXIuaHRtbCkuCgpBZnRlciB3ZSBjcmVhdGVkIHRoZSBleHBlcmltZW50IGFuZCBkZWNpZGVkIG9uIHRoZSBzYW1wbGUgc2l6ZSwgdGhlIG5leHQgc3RlcCBpcyB0byBwcmVyZXNpZ3RlciB0aGUgc3R1ZHkuIEhvd2V2ZXIsIGl0IHdvdWxkIGJlIGJldHRlciB0byBkbyBhIHBpbG90IHdpdGggNCBvciA1IHBhcnRpY2lwYW50cywgY2xlYW4gYWxsIHRoZSBkYXRhLCBkbyB0aGUgZGVzaXJlZCBhbmFseXNpcywgYW5kIHRoZW4gcHJlLXJlZ2lzdGVyIHRoZSBhbmFseXNpcyBhbmQgdGhvc2UgY29kZXMuIFlvdSBjYW4gZmluZCB0aGUgcHJlcmVnaXN0cmF0aW9uIGZvcm0gZm9yIHRoZSBjdXJyZW50IHN0dWR5IFtoZXJlXShodHRwczovL29zZi5pby83OXI2ZSkuCgpGaW5hbGx5LCB3ZSBuZWVkIHRvIHJlc3RydWN0dXJlIG91ciBwcm9qZWN0IGluIGEgdGlkeSBmb2xkZXIgd2l0aCBkaWZmZXJlbnQgc3ViLWZvbGRlcnMuIEhhdmluZyBhIGNsZWFuIGFuZCB0aWR5IGZvbGRlciBzdHJ1Y3R1cmUgY2FuIHNhdmUgdXMhIFRoZXJlIGFyZSBkaWZmZXJlbnQgZm9ybWF0cyBvZiBmb2xkZXIgc3RydWN0dXJlIChmb3IgZXhhbXBsZSwgc2VlIFtoZXJlXShodHRwOi8vbmlrb2xhLm1lL2ZvbGRlcl9zdHJ1Y3R1cmUuaHRtbCkgYW5kIFtoZXJlXShodHRwczovL3NsaWRlcy5jb20vZGpuYXZhcnJvL3dvcmtmbG93KSksIGJ1dCBmb3Igbm93LCB3ZSB1c2UgdGhlIGZvbGxvd2luZyBzdHJ1Y3R1cmU6CgpgYGB7ciBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjcwMHB4Iiwgb3V0LmhlaWdodD0iMjAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlKCdpbnB1dHMnLCdmb2xkZXJfc3RydWN0dXJlLnBuZycpKQpgYGAKCgojIEludHJvZHVjdGlvbiB0byBSCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIGV2YWw9Rn0KIyBsb2FkIGxpYnJhcmllcwpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShoZXJlKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoYnJvb20pCmxpYnJhcnkoYWZleCkKbGlicmFyeShlbW1lYW5zKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkoZ2dzY2kpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KHNraW1yKQojIGluc3RhbGwucGFja2FnZXMoImRldnRvb2xzIikKIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImVhc3lzdGF0cy9jb3JyZWxhdGlvbiIpCmxpYnJhcnkoImNvcnJlbGF0aW9uIikKb3B0aW9ucyhzY2lwZW49OTk5KSAjIHR1cm4gb2ZmIHNjaWVudGlmaWMgbm90YXRpb25zCm9wdGlvbnMoY29udHJhc3RzID0gYygnY29udHIuc3VtJywnY29udHIucG9seScpKSAjIHNldCB0aGUgY29udHJhc3Qgc3VtIGdsb2JhbGx5IApvcHRpb25zKGtuaXRyLmthYmxlLk5BID0gJycpCmBgYAoKUiBjYW4gYmUgdXNlZCBhcyBhIGNhbGN1bGF0b3IuIEZvciBtYXRoZW1hdGljYWwgcHVycG9zZXMsIGJlIGNhcmVmdWwgb2YgdGhlIG9yZGVyIGluIHdoaWNoIFIgZXhlY3V0ZXMgdGhlIGNvbW1hbmRzLgoKYGBge3J9CjEwICsgMTAKCjQgXiAyCgooMjUwIC8gNTAwKSAqIDEwMApgYGAKClIgaXMgYSBiaXQgZmxleGlibGUgd2l0aCBzcGFjaW5nIChidXQgbm8gc3BhY2luZyBpbiB0aGUgbmFtZSBvZiB2YXJpYWJsZXMgYW5kIHdvcmRzKQoKYGBge3J9CjEwKzEwCgoxMCAgICAgICAgICAgICAgICAgKyAgICAgICAgICAgMTAKYGBgCgpSIGNhbiBzb21ldGltZXMgdGVsbCB0aGF0IHlvdSdyZSBub3QgZmluaXNoZWQgeWV0CgpgYGB7ciBldmFsPUZ9CjEwICsKYGBgCgpIb3cgdG8gY3JlYXRlIGEgKnZhcmlhYmxlKj8gVmFyaWFibGUgYXNzaWdubWVudCB1c2luZyBgPC1gIGFuZCBgPWAuIE5vdGUgdGhhdCBSIGlzIGNhc2Ugc2Vuc2l0aXZlIGZvciBldmVyeXRoaW5nCgpgYGB7cn0KcGF5IDwtIDI1MAoKbW9udGggPSAxMgoKcGF5ICogbW9udGgKCnNhbGFyeSA8LSBwYXkgKiBtb250aApgYGAKCgpGZXcgcG9pbnRzIGluIG5hbWluZyB2YXJpYWJsZXMgYW5kIHZlY3RvcnM6IHVzZSBzaG9ydCwgaW5mb3JtYXRpdmUgd29yZHMsIGtlZXAgc2FtZSBtZXRob2QgKGUuZy4sIG5vdCB1c2luZyBjYXBpdGFsIHdvcmRzLCB1c2Ugb25seSBfIG9yIC4gKS4KCiMjIEZ1bmN0aW9uIApGdW5jdGlvbiBpcyBhIHNldCBvZiBzdGF0ZW1lbnRzIGNvbWJpbmVkIHRvZ2V0aGVyIHRvIHBlcmZvcm0gYSBzcGVjaWZpYyB0YXNrLiBXaGVuIHdlIHVzZSBhIGJsb2NrIG9mIGNvZGUgcmVwZWF0ZWRseSwgd2UgY2FuIGNvbnZlcnQgaXQgdG8gYSBmdW5jdGlvbi4gVG8gd3JpdGUgYSBmdW5jdGlvbiwgZmlyc3QsIHlvdSBuZWVkIHRvICpkZWZpbmUqIGl0OgoKYGBge3J9Cm15X211bHRpcGxpZXIgPC0gZnVuY3Rpb24oYSxiKXsKICByZXN1bHQgPSBhICogYgogIHJldHVybiAocmVzdWx0KQp9CmBgYAoKVGhpcyBjb2RlIGRvIG5vdGhpbmcuIFRvIGdldCBhIHJlc3VsdCwgeW91IG5lZWQgdG8gKmNhbGwqIGl0OgoKYGBge3J9Cm15X211bHRpcGxpZXIgKDIsNCkKYGBgCgpGb3J0dW5hdGVseSwgeW91IGRvIG5vdCBuZWVkIHRvIHdyaXRlIGV2ZXJ5dGhpbmcgZnJvbSBzY3JhdGNoLiBSIGhhcyBsb3RzIG9mIGJ1aWx0LWluIGZ1bmN0aW9ucyB0aGF0IHlvdSBjYW4gdXNlOgpgYGB7cn0Kcm91bmQoNTQuNjc4NykKcm91bmQoNTQuNTc4NywgZGlnaXRzID0gMikKYGBgCgpVc2UgYD9gIGJlZm9yZSB0aGUgZnVuY3Rpb24gbmFtZSB0byBnZXQgc29tZSBoZWxwLiBGb3IgZXhhbXBsZSwgYD9yb3VuZGAuIFlvdSB3aWxsIHNlZSBtYW55IGZ1bmN0aW9ucyBpbiB0aGUgcmVzdCBvZiB0aGUgd29ya3Nob3AuCgojIyBCYXNpYyBEYXRhIFR5cGVzIGluIFI6CgpmdW5jdGlvbiBgY2xhc3MoKWAgaXMgdXNlZCB0byBzaG93IHdoYXQgaXMgdGhlIHR5cGUgb2YgYSB2YXJpYWJsZS4KCgoxLiAqTG9naWNhbCo6IGBUUlVFYCwgYEZBTFNFYCBjYW4gYmUgYWJicmV2aWF0ZWQgYXMgYFRgLCBgRmAuICBUaGV5IGhhcyB0byBiZSBjYXBpdGFsLCAndHJ1ZScgaXMgbm90IGEgbG9naWNhbCBkYXRhOgpgYGB7cn0KY2xhc3MoVFJVRSkKY2xhc3MoRikKYGBgCgoyLiAqTnVtZXJpYyo6IGFsbCBudW1iZXJzIGUuZy4gNSwgIDEwLjUsICAxMSwzNzsgIGEgc3BlY2lhbCB0eXBlIG9mIG51bWVyaWMgaXMgImludGVnZXIiIHdoaWNoIGlzIG51bWJlcnMgd2l0aG91dCBkZWNpbWFsLiBJbnRlZ2VycyBhcmUgYWx3YXlzIG51bWVyaWMsIGJ1dCBudW1lcmljIGlzIG5vdCBhbHdheXMgaW50ZWdlcjoKYGBge3J9CmNsYXNzKDIpCmNsYXNzKDEzLjQ2KQpgYGAKCjMuICpDaGFyYWN0ZXIqOiB0ZXh0IGZvciBleGFtcGxlLCAiSSBsb3ZlIFIiIG9yICI0IiBvciAiNC41IjoKYGBge3J9CmNsYXNzKCJoYSBoYSBoYSBoYSIpCmNsYXNzKCI1Ni42IikKY2xhc3MoIlRSVUUiKQpgYGAKCkNhbiB3ZSBjaGFuZ2UgdGhlIHR5cGUgb2YgZGF0YSBpbiBhIHZhcmlhYmxlPyBZZXMsIHlvdSBuZWVkIHRvIHVzZSB0aGUgZnVuY3Rpb24gYGFzLi0tLSgpYAoKYGBge3J9CmFzLm51bWVyaWMoVFJVRSkKYXMuY2hhcmFjdGVyKDQpCmFzLm51bWVyaWMoIjQuNSIpCmFzLm51bWVyaWMoIkhlbGxvIikKYGBgCgoKIyMgRGF0YSBTdHJ1Y3R1cmVzIGluIFIKCgoqKlZlY3RvcioqOiB3aGVuIHRoZXJlIGFyZSBtb3JlIHRoYW4gb25lIG51bWJlciBvciBsZXR0ZXIgc3RvcmVkLiBVc2UgdGhlIGNvbWJpbmUgZnVuY3Rpb24gYygpIGZvciB0aGF0LgoKYGBge3J9CnNhbGUgPC0gYygxLCAyLCAzLDQsIDUsIDYsIDcsIDgsIDksIDEwKSAjIGFsc28gc2FsZSA8LSBjKDE6MTApCgpzYWxlIDwtIGMoMToxMCkKCnNhbGUgKiBzYWxlCmBgYAoKKlN1YnNldHRpbmcgYSB2ZWN0b3IqOgoKYGBge3J9CmRheXMgPC0gYygiU2F0dXJkYXkiLCAiU3VuZGF5IiwgIk1vbmRheSIsICJUdWVzZGF5IiwgIldlZG5lc2RheSIsICJUaHVyc2RheSIsICJGcmlkYXkiKQoKZGF5c1syXQpkYXlzWy0yXQoKZGF5c1tjKDIsIDMsIDQpXQpgYGAKCgojIyMgRXhlcmNpc2U6CgpDcmVhdGUgYSB2ZWN0b3IgbmFtZWQgYG15X3ZlY3RvcmAgd2l0aCBudW1iZXJzIGZyb20gMCB0byAxMDAwIGluIGl0OgoKYGBge3J9Cm15X3ZlY3RvciA8LSAoMDoxMDAwKQoKbWVhbihteV92ZWN0b3IpCm1lZGlhbihteV92ZWN0b3IpCm1pbihteV92ZWN0b3IpCnJhbmdlKG15X3ZlY3RvcikKY2xhc3MobXlfdmVjdG9yKQpzdW0obXlfdmVjdG9yKQpzZChteV92ZWN0b3IpCmBgYAoKKipMaXN0Kio6IGFsbG93cyB5b3UgdG8gZ2F0aGVyIGEgdmFyaWV0eSBvZiBvYmplY3RzIHVuZGVyIG9uZSBuYW1lICh0aGF0IGlzLCB0aGUgbmFtZSBvZiB0aGUgbGlzdCkgaW4gYW4gb3JkZXJlZCB3YXkuIFRoZXNlIG9iamVjdHMgY2FuIGJlIG1hdHJpY2VzLCB2ZWN0b3JzLCBkYXRhIGZyYW1lcywgZXZlbiBvdGhlciBsaXN0LgoKYGBge3J9Cm15X2xpc3QgPSBsaXN0KHNhbGUsIDEsIDMsIDQ6NywgIkhFTExPIiwgImhlbGxvIiwgRkFMU0UpCm15X2xpc3QKYGBgCgoqKkZhY3RvcioqOiBGYWN0b3JzIHN0b3JlIHRoZSB2ZWN0b3IgYWxvbmcgd2l0aCB0aGUgZGlzdGluY3QgdmFsdWVzIG9mIHRoZSBlbGVtZW50cyBpbiB0aGUgdmVjdG9yIGFzIGxhYmVscy4gVGhlIGxhYmVscyBhcmUgYWx3YXlzIGNoYXJhY3RlciBpcnJlc3BlY3RpdmUgb2Ygd2hldGhlciBpdCBpcyBudW1lcmljIG9yIGNoYXJhY3Rlci4gRm9yIGV4YW1wbGUsIHZhcmlhYmxlIGdlbmRlciB3aXRoICJtYWxlIiBhbmQgImZlbWFsZSIgZW50cmllczoKCmBgYHtyfQpnZW5kZXIgPC0gYygibWFsZSIsICJtYWxlIiwgIm1hbGUiLCAiZmVtYWxlIiwgImZlbWFsZSIsICJmZW1hbGUiKQpnZW5kZXIgPC0gZmFjdG9yKGdlbmRlcikKYGBgCgpSIG5vdyB0cmVhdHMgZ2VuZGVyIGFzIGEgbm9taW5hbCAoY2F0ZWdvcmljYWwpIHZhcmlhYmxlOiAxPWZlbWFsZSwgMj1tYWxlIGludGVybmFsbHkgKGFscGhhYmV0aWNhbGx5KS4KYGBge3J9CnN1bW1hcnkoZ2VuZGVyKQpgYGAKCipRdWVzdGlvbio6IHdoeSB3aGVuIHdlIHJhbiB0aGUgYWJvdmUgZnVuY3Rpb24gaS5lLiBzdW1tYXJ5KCksIGl0IHNob3dlZCB0aHJlZSBhbmQgbm90IHR3byBsZXZlbHMgb2YgdGhlIGRhdGE/ICpIaW50KjogcnVuICdnZW5kZXInLgoKYGBge3J9CmdlbmRlcgpgYGAKClNvLCBiZSBjYXJlZnVsIG9mIHNwYWNlcyEKCiMjIyBFeGVyY2lzZToKQ3JlYXRlIGEgZ2VuZGVyIGZhY3RvciB3aXRoIDMwIG1hbGUgYW5kIDQwIGZlbWFsZXMgKCpIaW50KjogdXNlIHRoZSBgcmVwKClgIGZ1bmN0aW9uKToKYGBge3J9CmdlbmRlciA8LSBjKHJlcCgibWFsZSIsMzApLCByZXAoImZlbWFsZSIsIDQwKSkKZ2VuZGVyIDwtIGZhY3RvcihnZW5kZXIpCmdlbmRlcgpgYGAKClRoZXJlIGFyZSB0d28gdHlwZXMgb2YgY2F0ZWdvcmljYWwgdmFyaWFibGVzOiBub21pbmFsIGFuZCBvcmRpbmFsLiBIb3cgdG8gY3JlYXRlIG9yZGVyZWQgZmFjdG9ycyAod2hlbiB0aGUgdmFyaWFibGUgaXMgbm9taW5hbCBhbmQgdmFsdWVzIGNhbiBiZSBvcmRlcmVkKT8gV2Ugc2hvdWxkIGFkZCB0d28gYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gdGhlIGBmYWN0b3IoKWAgZnVuY3Rpb246IGBvcmRlcmVkID0gVFJVRWAsIGFuZCBgbGV2ZWxzID0gYygibGV2ZWwxIiwgImxldmVsMiIpYC4gRm9yIGV4YW1wbGUsIHdlIGhhdmUgYSB2ZWN0b3IgdGhhdCBzaG93cyBwYXJ0aWNpcGFudHMnIGVkdWNhdGlvbiBsZXZlbC4KCmBgYHtyfQplZHU8LWMoMywyLDMsNCwxLDIsMiwzLDQpCgplZHVjYXRpb248LWZhY3RvcihlZHUsIG9yZGVyZWQgPSBUUlVFKQpsZXZlbHMoZWR1Y2F0aW9uKSA8LSBjKCJQcmltYXJ5IHNjaG9vbCIsImhpZ2ggc2Nob29sIiwiQ29sbGVnZSIsIlVuaSBncmFkdWF0ZWQiKQplZHVjYXRpb24KYGBgCgojIyMgRXhlcmNpc2U6CldlIGhhdmUgYSBmYWN0b3Igd2l0aCBgcGF0aWVudGAgYW5kIGBjb250cm9sYCB2YWx1ZXMuIEhlcmUsIHRoZSBmaXJzdCBsZXZlbCBpcyBjb250cm9sIGFuZCB0aGUgc2Vjb25kIGxldmVsIGlzIHBhdGllbnQuIENoYW5nZSB0aGUgb3JkZXIgb2YgbGV2ZWxzLCBzbyBwYXRpZW50IHdvdWxkIGJlIHRoZSBmaXJzdCBsZXZlbDoKCmBgYHtyfQpoZWFsdGhfc3RhdHVzIDwtIGZhY3RvcihjKHJlcCgncGF0aWVudCcsNSkscmVwKCdjb250cm9sJyw1KSkpCmhlYWx0aF9zdGF0dXMKCmhlYWx0aF9zdGF0dXNfcmVvcmRlcmVkIDwtIGZhY3RvcihoZWFsdGhfc3RhdHVzLCBsZXZlbHMgPSBjKCdwYXRpZW50JywnY29udHJvbCcpKQpoZWFsdGhfc3RhdHVzX3Jlb3JkZXJlZApgYGAKCkZpbmFsbHksIGNhbiB5b3UgcmVsYWJlbCBib3RoIGxldmVscyB0byB1cHBlcmNhc2UgY2hhcmFjdGVycz8gKCpIaW50KjogY2hlY2sgYD9mYWN0b3JgKQoKYGBge3J9CmhlYWx0aF9zdGF0dXNfcmVsYWJlbGVkIDwtIGZhY3RvcihoZWFsdGhfc3RhdHVzLCBsZXZlbHMgPSBjKCdwYXRpZW50JywnY29udHJvbCcpLCBsYWJlbHMgPSBjKCdQYXRpZW50JywnQ29udHJvbCcpKQpoZWFsdGhfc3RhdHVzX3JlbGFiZWxlZApgYGAKCgoqKk1hdHJpY2VzKio6IEFsbCBjb2x1bW5zIGluIGEgbWF0cml4IG11c3QgaGF2ZSB0aGUgc2FtZSBtb2RlKG51bWVyaWMsIGNoYXJhY3RlciwgZXRjLikgYW5kIHRoZSBzYW1lIGxlbmd0aC4gSXQgY2FuIGJlIGNyZWF0ZWQgdXNpbmcgYSB2ZWN0b3IgaW5wdXQgdG8gdGhlIG1hdHJpeCBmdW5jdGlvbi4KCmBgYHtyfQpteV9tYXRyaXggPSBtYXRyaXgoYygxLDIsMyw0LDUsNiw3LDgsOSksIG5yb3cgPSAzLCBuY29sID0gMykKCm15X21hdHJpeApgYGAKCioqRGF0YSBmcmFtZXMqKjogKHR3by1kaW1lbnNpb25hbCBvYmplY3RzKSBjYW4gaG9sZCBudW1lcmljLCBjaGFyYWN0ZXIgb3IgbG9naWNhbCB2YWx1ZXMuIFdpdGhpbiBhIGNvbHVtbiBhbGwgZWxlbWVudHMgaGF2ZSB0aGUgc2FtZSBkYXRhIHR5cGUsIGJ1dCBkaWZmZXJlbnQgY29sdW1ucyBjYW4gYmUgb2YgZGlmZmVyZW50IGRhdGEgdHlwZS4gTGV0J3MgY3JlYXRlIGEgZGF0YWZyYW1lOgoKYGBge3J9CmlkIDwtIDE6MjAwCmdyb3VwIDwtIGMocmVwKCJQc3ljaG90aGVyYXB5IiwgMTAwKSwgcmVwKCJNZWRpY2F0aW9uIiwgMTAwKSkKcmVzcG9uc2UgPC0gYyhybm9ybSgxMDAsIG1lYW4gPSAzMCwgc2QgPSA1KSwKICAgICAgICAgICAgIHJub3JtKDEwMCwgbWVhbiA9IDI1LCBzZCA9IDUpKQoKbXlfZGF0YWZyYW1lIDwtZGF0YS5mcmFtZShQYXRpZW50ID0gaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgVHJlYXRtZW50ID0gZ3JvdXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgUmVzcG9uc2UgPSByZXNwb25zZSkKYGBgCgpXZSBhbHNvIGNvdWxkIGhhdmUgZG9uZSB0aGUgYmVsb3cKCmBgYHtyfQpteV9kYXRhZnJhbWUgPC1kYXRhLmZyYW1lKFBhdGllbnQgPSBjKDE6MjAwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBUcmVhdG1lbnQgPSBjKHJlcCgiUHN5Y2hvdGhlcmFweSIsIDEwMCksIHJlcCgiTWVkaWNhdGlvbiIsIDEwMCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIFJlc3BvbnNlID0gYyhybm9ybSgxMDAsIG1lYW4gPSAzMCwgc2QgPSA1KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm5vcm0oMTAwLCBtZWFuID0gMjUsIHNkID0gNSkpKQpgYGAKCkluIGxhcmdlIGRhdGEgc2V0cywgdGhlIGZ1bmN0aW9uIGhlYWQoKSBlbmFibGVzIHlvdSB0byBzaG93IHRoZSBmaXJzdCBvYnNlcnZhdGlvbnMgb2YgYSBkYXRhIGZyYW1lcy4gU2ltaWxhcmx5LCB0aGUgZnVuY3Rpb24gdGFpbCgpIHByaW50cyBvdXQgdGhlIGxhc3Qgb2JzZXJ2YXRpb25zIGluIHlvdXIgZGF0YSBzZXQuCgpgYGB7ciBldmFsPUZ9CmhlYWQobXlfZGF0YWZyYW1lKSAKdGFpbChteV9kYXRhZnJhbWUpCmBgYAoKYGBge3IgZWNobz1GfQpoZWFkKG15X2RhdGFmcmFtZSkgJT4lCiAga25pdHI6OmthYmxlKCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiYm9yZGVyZWQiLCAiY29uZGVuc2VkIiksIGZpeGVkX3RoZWFkID0gVCwgZnVsbF93aWR0aCA9IFQpCnRhaWwobXlfZGF0YWZyYW1lKSU+JQogIGtuaXRyOjprYWJsZSgpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImJvcmRlcmVkIiwgImNvbmRlbnNlZCIpLCBmaXhlZF90aGVhZCA9IFQsIGZ1bGxfd2lkdGggPSBUKQpgYGAKClNpbWlsYXIgdG8gdmVjdG9ycyBhbmQgbWF0cmljZXMsIGJyYWNrZXRzIFtdIGFyZSB1c2VkIHRvIHNlbGVjdHMgZGF0YSBmcm9tIHJvd3MgYW5kIGNvbHVtbnMgaW4gZGF0YS5mcmFtZXM6CgpgYGB7cn0KbXlfZGF0YWZyYW1lWzM1LCAzXQpgYGAKCiMjIyBFeGVyY2lzZQoKSG93IGNhbiB3ZSBnZXQgYWxsIGNvbHVtbnMsIGJ1dCBvbmx5IGZvciB0aGUgZmlyc3QgMTAgcGFydGljaXBhbnRzPwoKYGBge3IgZXZhbD1GfQpteV9kYXRhZnJhbWVbMToxMCwgXQpgYGAKCmBgYHtyIGVjaG89Rn0Ka25pdHI6OmthYmxlKG15X2RhdGFmcmFtZVsxOjEwLCBdKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJib3JkZXJlZCIsICJjb25kZW5zZWQiKSwgZml4ZWRfdGhlYWQgPSBULCBmdWxsX3dpZHRoID0gVCkKCmBgYApIb3cgdG8gZ2V0IG9ubHkgdGhlIFJlc3BvbnNlIGNvbHVtbiBmb3IgYWxsIHBhcnRpY2lwYW50cz8KCmBgYHtyfQpteV9kYXRhZnJhbWVbICwgM10KYGBgCgpBbm90aGVyIGVhc2llciB3YXkgZm9yIHNlbGVjdGluZyBwYXJ0aWN1bGFyIGl0ZW1zIGlzIHVzaW5nIHRoZWlyIG5hbWVzIHRoYXQgaXMgbW9yZSBoZWxwZnVsIHRoYW4gbnVtYmVyIG9mIHRoZSByb3dzIGluIGxhcmdlIGRhdGEgc2V0czoKYGBge3IgZXZhbD1GfQpteV9kYXRhZnJhbWVbICwgIlJlc3BvbnNlIl0KIyBPUjoKbXlfZGF0YWZyYW1lJFJlc3BvbnNlCgpgYGAKCgojIERhdGEgQ2xlYW5pbmcKCk5vdywgc3VwcG9zZSB3ZSB0ZXN0ZWQgMTQxIHN0dWRlbnRzLiBGaXJzdCwgbGV0J3MgcmVhZCBhbmQgY2hlY2sgdGhlIHVuY2xlYW5lZCBkYXRhOgpgYGB7ciBtZXNzYWdlPUYsIHdhcm5pbmc9RiwgZXZhbD1GfQojIHJlYWQgdGhlIHJhdyBkYXRhCnJhd19kYXRhIDwtIHJlYWRfY3N2KGhlcmUoInJhd19kYXRhIiwicmF3X2FyZ3VtZW50YXRpdmVfZXhwMS5jc3YiKSkKaGVhZChyYXdfZGF0YSkKYGBgCgpgYGB7ciBtZXNzYWdlPUYsIHdhcm5pbmc9RiwgZWNobz1GfQojIHJlYWQgdGhlIHJhdyBkYXRhCnJhd19kYXRhIDwtIHJlYWRfY3N2KGhlcmUoInJhd19kYXRhIiwicmF3X2FyZ3VtZW50YXRpdmVfZXhwMS5jc3YiKSkKCmtuaXRyOjprYWJsZShoZWFkKHJhd19kYXRhKSkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiYm9yZGVyZWQiLCAiY29uZGVuc2VkIiksIGZpeGVkX3RoZWFkID0gVCwgZnVsbF93aWR0aCA9IEYpJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICI3ODBweCIpCmBgYAoKTm93LCBsZXQncyBkbyBzb21lIGNsZWFuaW5pbmcgdXNpbmcgYGRwbHlyYCwgYHRpZHlyYCBhbmQgb3RoZXIgYHRpZHl2ZXJzZWAgbGlicmFyaWVzLiBGaW5hbGx5LCB3ZSB3aWxsIGNoZWNrIHRoZSBkYXRhOgpgYGB7ciBtZXNzYWdlPUYsIHdhcm5pbmc9RiwgZXZhbD1GfQpjbGVhbmVkX2RhdGEgPC0gcmF3X2RhdGEgJT4lIAogIGZpbHRlcihwcm9ncmVzcyA9PSAxMDApICU+JSAjIGZpbHRlciBvdXQgdW5maW5pc2hlZCBwYXJ0aWNpcGFudHMKICBzZWxlY3QoLWVuZF9kYXRlLCAtc3RhdHVzLC1pcF9hZGRyZXNzLCAtZHVyYXRpb25faW5fc2Vjb25kcywgLXJlY29yZGVkX2RhdGU6LXVzZXJfbGFuZ3VhZ2UpICU+JSAjcmVtb3ZlIHNvbWUgdXNlbGVzcyBjb2x1bW5zCiAgbXV0YXRlKGFvdGVfdG90YWw9IGFvdGUxK2FvdGUyK2FvdGUzK2FvdGU0K2FvdGU1K2FvdGU2K2FvdGU3K2FvdGU4LCAjIGNyZWF0ZSBhIHRvdGFsIHNjb3JlIGZvciBvdXIgcXVlc3Rpb25uYWlyZQogICAgICAgICBhdHRlbnRpdmU9IGNhc2Vfd2hlbihhdHRlbnRpb25fY29ycmVjdCA+PSAyfiAnWWVzJyxUfiAnTm8nKSkgJT4lCiAgbXV0YXRlKGNydDE9IGNhc2Vfd2hlbihjcnQxPT0nNCd+IDEsVH4wKSwKICAgICAgICAgY3J0Mj0gY2FzZV93aGVuKGNydDI9PScxMCd+IDEsVH4wKSwKICAgICAgICAgY3J0Mz0gY2FzZV93aGVuKGNydDM9PSczOSd+IDEsVH4wKSwKICAgICAgICAgY3J0X3RvdGFsPSBjcnQxICsgY3J0MiArIGNydDMpICU+JQogIHNlbGVjdCgtYXR0ZW50aW9uMTotYW90ZTgpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYyhzdGFnZTFfc2ltcGxlOnN0YWdlN19zaW1wbGUsc3RhZ2UxX2NvbXBsZXg6c3RhZ2U3X2NvbXBsZXgpLG5hbWVzX3RvID0gJ3N0YWdlJyx2YWx1ZXNfdG8gPSAndHJ1dGhfZXN0aW1hdGUnKSAlPiUgIyBtYWtlIG91ciBkYXRhZnJhbWUgbG9uZwogICNwaXZvdF93aWRlcihuYW1lc19mcm9tID0gc3RhZ2UsIHZhbHVlc19mcm9tPSB0cnV0aF9lc3RpbWF0ZSkgIyB0aGlzIGNvZGUgY2hhbmdlIG91ciBkYXRhZnJhbWUgYmFjayB0byB3aWRlCiAgZmlsdGVyKCFpcy5uYSh0cnV0aF9lc3RpbWF0ZSkpICU+JSAjcmVtb3ZlIHJvd3Mgd2l0aCB0cnV0aF9lc3RpbWF0ZSA9PSBOQQogIG11dGF0ZShzdGFnZT0gZ3N1YigiXy4qIiwgIiIsIHN0YWdlKSkgJT4lCiAgcmVuYW1lKGNvbnNlbnQ9IGNvbnNlbnRfZm9ybSkgJT4lICMgcmVuYW1lIGEgY29sdW1uCiAgI211dGF0ZV9pZihpcy5jaGFyYWN0ZXIsIGZhY3RvcikgJT4lCiAgbXV0YXRlKHN1YmplY3Q9IGZhY3RvcihzdWJqZWN0KSwgIyBjb252ZXJ0IGFsbCBjaGFyYWN0ZXJzIHRvIGZhY3RvcgogICAgICAgICBncm91cCA9IGZhY3Rvcihncm91cCksCiAgICAgICAgIGF0dGVudGl2ZSA9IGZhY3RvcihhdHRlbnRpdmUpLAogICAgICAgICBzdGFnZSA9IGZhY3RvcihzdGFnZSkpCmBgYAoKCmBgYHtyIG1lc3NhZ2U9Riwgd2FybmluZz1GLCBlY2hvPUZ9CmNsZWFuZWRfZGF0YSA8LSByYXdfZGF0YSAlPiUgCiAgZmlsdGVyKHByb2dyZXNzID09IDEwMCkgJT4lICMgZmlsdGVyIG91dCB1bmZpbmlzaGVkIHBhcnRpY2lwYW50cwogIHNlbGVjdCgtZW5kX2RhdGUsIC1zdGF0dXMsLWlwX2FkZHJlc3MsIC1kdXJhdGlvbl9pbl9zZWNvbmRzLCAtcmVjb3JkZWRfZGF0ZTotdXNlcl9sYW5ndWFnZSkgJT4lICNyZW1vdmUgc29tZSB1c2VsZXNzIGNvbHVtbnMKICBtdXRhdGUoYW90ZV90b3RhbD0gYW90ZTErYW90ZTIrYW90ZTMrYW90ZTQrYW90ZTUrYW90ZTYrYW90ZTcrYW90ZTgsICMgY3JlYXRlIGEgdG90YWwgc2NvcmUgZm9yIG91ciBxdWVzdGlvbm5haXJlCiAgICAgICAgIGF0dGVudGl2ZT0gY2FzZV93aGVuKGF0dGVudGlvbl9jb3JyZWN0ID49IDJ+ICdZZXMnLFR+ICdObycpKSAlPiUKICBtdXRhdGUoY3J0MT0gY2FzZV93aGVuKGNydDE9PSc0J34gMSxUfjApLAogICAgICAgICBjcnQyPSBjYXNlX3doZW4oY3J0Mj09JzEwJ34gMSxUfjApLAogICAgICAgICBjcnQzPSBjYXNlX3doZW4oY3J0Mz09JzM5J34gMSxUfjApLAogICAgICAgICBjcnRfdG90YWw9IGNydDEgKyBjcnQyICsgY3J0MykgJT4lCiAgc2VsZWN0KC1hdHRlbnRpb24xOi1hb3RlOCkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKHN0YWdlMV9zaW1wbGU6c3RhZ2U3X3NpbXBsZSxzdGFnZTFfY29tcGxleDpzdGFnZTdfY29tcGxleCksbmFtZXNfdG8gPSAnc3RhZ2UnLHZhbHVlc190byA9ICd0cnV0aF9lc3RpbWF0ZScpICU+JSAjIG1ha2Ugb3VyIGRhdGFmcmFtZSBsb25nCiAgI3Bpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzdGFnZSwgdmFsdWVzX2Zyb209IHRydXRoX2VzdGltYXRlKSAjIHRoaXMgY29kZSBjaGFuZ2Ugb3VyIGRhdGFmcmFtZSBiYWNrIHRvIHdpZGUKICBmaWx0ZXIoIWlzLm5hKHRydXRoX2VzdGltYXRlKSkgJT4lICNyZW1vdmUgcm93cyB3aXRoIHRydXRoX2VzdGltYXRlID09IE5BCiAgbXV0YXRlKHN0YWdlPSBnc3ViKCJfLioiLCAiIiwgc3RhZ2UpKSAlPiUKICByZW5hbWUoY29uc2VudD0gY29uc2VudF9mb3JtKSAlPiUgIyByZW5hbWUgYSBjb2x1bW4KICAjbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgZmFjdG9yKSAlPiUKICBtdXRhdGUoc3ViamVjdD0gZmFjdG9yKHN1YmplY3QpLCAjIGNvbnZlcnQgYWxsIGNoYXJhY3RlcnMgdG8gZmFjdG9yCiAgICAgICAgIGdyb3VwID0gZmFjdG9yKGdyb3VwKSwKICAgICAgICAgYXR0ZW50aXZlID0gZmFjdG9yKGF0dGVudGl2ZSksCiAgICAgICAgIHN0YWdlID0gZmFjdG9yKHN0YWdlKSkKCmtuaXRyOjprYWJsZShoZWFkKGNsZWFuZWRfZGF0YSkpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImJvcmRlcmVkIiwgImNvbmRlbnNlZCIpLCBmaXhlZF90aGVhZCA9IFQsIGZ1bGxfd2lkdGggPSBGKSU+JQogIHNjcm9sbF9ib3god2lkdGggPSAiNzgwcHgiKQpgYGAKCk9rLCBub3cgdGhlIGRhdGEgaXMgY2xlYW4gYW5kIHRpZHkgd2hpY2ggbWVhbnM6Cgo+IDEuIEVhY2ggdmFyaWFibGUgZm9ybXMgYSBjb2x1bW4uCjIuIEVhY2ggb2JzZXJ2YXRpb24gZm9ybXMgYSByb3cuCjMuIEVhY2ggdHlwZSBvZiBvYnNlcnZhdGlvbmFsIHVuaXQgZm9ybXMgYSB0YWJsZSAoW1dpY2toYW1dKGh0dHBzOi8vdml0YS5oYWQuY28ubnovcGFwZXJzL3RpZHktZGF0YS5wZGYpLCAyMDE0KS4KCkNoZWNrIHRoZSBkYXRhZnJhbWUgYW5kIGFsbCB0aGUgZGF0YSB0eXBlczoKYGBge3J9CnN0cihjbGVhbmVkX2RhdGEpCmBgYAoKRmluYWxseSwgd2Ugc2F2ZSBvdXIgZGF0YSB0byB0aGUgYGNsZWFuZWRfZGF0YWAgZm9sZGVyLgoKYGBge3J9CndyaXRlX2NzdihjbGVhbmVkX2RhdGEsIGhlcmUoImNsZWFuZWRfZGF0YSIsImFyZ3VtZW50YXRpdmVfZXhwMS5jc3YiKSkKYGBgCgojIERlc2NyaXB0aXZlIFN0YXRpc3RpY3MKCj4gTm90ZTogQWxsIHRoZSBkYXRhIHRoYXQgd2UgdXNlIGhlcmUgaXMgbWFuaXB1bGF0ZWQgKGZhYnJpY2F0ZWQpIGZvciB0ZWFjaGluZyBwdXJwdXNlcy4gSW4gb3VyIHN0dWR5LCB3ZSBmYWlsZWQgdG8gZmluZCBzdWNoIGJlYXV0aWZ1bCBhbmQgaW50ZXJlc3RpbmcgcmVzdWx0cy4KCk5vdywgbGV0J3MgZG8gc29tZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzLiBGaXJzdCwgd2UgY2FuIG9wZW4gYSBuZXcgc2NyaXB0IGNhbGxlZCBgYW5hbHlzaXNfZXhwMS5yYCBhbmQgcmVhZCB0aGUgY2xlYW5lZCBkYXRhIGFnYWluLiAKCmBgYHtyIG1lc3NhZ2U9Riwgd2FybmluZz1GLH0KZGF0YV9leHAxIDwtIHJlYWRfY3N2KGhlcmUoImNsZWFuZWRfZGF0YSIsImFyZ3VtZW50YXRpdmVfZXhwMS5jc3YiKSkKYGBgCgpIb3cgbWFueSBwYXJ0aWNpcGFudHMgaW4gdG90YWw/CgpgYGB7ciBtZXNzYWdlPUYsIHdhcm5pbmc9RiwgZXZhbD1GfQpkYXRhX2V4cDEgJT4lIHN1bW1hcmlzZShuPSBuX2Rpc3RpbmN0KHN1YmplY3QpKQpgYGAKCgpgYGB7ciBtZXNzYWdlPUYsIHdhcm5pbmc9RiwgZWNobz1GfQpkYXRhX2V4cDEgJT4lIHN1bW1hcmlzZShuPSBuX2Rpc3RpbmN0KHN1YmplY3QpKSU+JQogIGtuaXRyOjprYWJsZSgpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImJvcmRlcmVkIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRikKYGBgCgpob3cgbWFueSBwYXJ0aWNpcGFudHMgaW4gZWFjaCBncm91cD8KYGBge3IgbWVzc2FnZT1GLCB3YXJuaW5nPUYsIGV2YWw9Rn0KZGF0YV9leHAxICU+JSAKICBncm91cF9ieShzdWJqZWN0KSAlPiUgCiAgZmlsdGVyKHJvd19udW1iZXIoKT09MSkgJT4lIAogIHVuZ3JvdXAgKCkgJT4lIAogIGdyb3VwX2J5KGdyb3VwKSAlPiUgCiAgY291bnQoKSAKYGBgCgpgYGB7ciBtZXNzYWdlPUYsIHdhcm5pbmc9RiwgZWNobz1GfQpkYXRhX2V4cDEgJT4lIGdyb3VwX2J5KHN1YmplY3QpICU+JSBmaWx0ZXIocm93X251bWJlcigpPT0xKSAlPiUgdW5ncm91cCAoKSAlPiUgZ3JvdXBfYnkoZ3JvdXApICU+JSBjb3VudCgpICU+JQogIGtuaXRyOjprYWJsZSgpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImJvcmRlcmVkIiwgImNvbmRlbnNlZCIpLCBmaXhlZF90aGVhZCA9IFQpCmBgYAoKRmluZCB0aGUgbWVhbiBhbmQgc2QgZm9yIG51bWVyaWMgdmFyaWFibGVzIHVzaW5nIGJhc2UgUiBgc3VtbWFyeWAgZnVuY3Rpb246CgpgYGB7cn0KZGF0YV9leHAxICU+JSAKICBncm91cF9ieShzdWJqZWN0KSAlPiUgCiAgZmlsdGVyKHJvd19udW1iZXIoKT09MSkgJT4lIAogIHVuZ3JvdXAgKCkgJT4lCiAgc3VtbWFyeSgpCmBgYAoKQWx0ZXJuYXRpdmVseSwgd2UgY2FuIHVzZSBgYmFzZSBSIGBzdW1tYXJ5YCBmdW5jdGlvbmBza2ltcmAgbGlicmFyeToKYGBge3IgZXZhbD1GfQpkYXRhX2V4cDEgJT4lIAogIGdyb3VwX2J5KHN1YmplY3QpICU+JSAKICBmaWx0ZXIocm93X251bWJlcigpPT0xKSAlPiUgCiAgdW5ncm91cCAoKSAlPiUgCiAgZHBseXI6OnNlbGVjdCAoYWdlLCBudW1lcmFjeV90b3RhbCwgbWluZHdhcmVfdG90YWwsIGFvdGVfdG90YWwsIGNydF90b3RhbCkgJT4lIAogIHNraW1yOjpza2ltKCkKYGBgCgpgYGB7ciBlY2hvPUZ9CmRhdGFfZXhwMSAlPiUgCiAgZ3JvdXBfYnkoc3ViamVjdCkgJT4lIAogIGZpbHRlcihyb3dfbnVtYmVyKCk9PTEpICU+JSAKICB1bmdyb3VwICgpICU+JSAKICBkcGx5cjo6c2VsZWN0IChhZ2UsIG51bWVyYWN5X3RvdGFsLCBtaW5kd2FyZV90b3RhbCwgYW90ZV90b3RhbCwgY3J0X3RvdGFsKSAlPiUgCiAgc2tpbXI6OnNraW0oKSAlPiUKICBrbml0cjo6a2FibGUoKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJib3JkZXJlZCIsICJjb25kZW5zZWQiKSwgZml4ZWRfdGhlYWQgPSBULCBmdWxsX3dpZHRoID0gRiklPiUKICBzY3JvbGxfYm94KHdpZHRoID0gIjc4MHB4IikKYGBgCgoKIyMjIEV4ZXJjaXNlCgpGb3IgdGhpcyBleGVyY2lzZSwgd2UgdXNlIGEgZGF0YXNldCBvZiBvbmUgb2YgbXkgb3duIHN0dWRpZXMuIEluIHRoaXMgc3R1ZHksIHdlIGFza2VkIHBhcnRpY2lwYW50cyB0byBndWVzcyB0aGUgcGh5c2ljYWwgYnJpZ2h0bmVzcyBvZiByZWFzb25pbmcgYXJndW1lbnRzIGFuZCB0aGVuIHdlIGdhdmUgYSBjb2duaXRpdmUgYWJpbGl0eSB0ZXN0LiAoU2VlIHRoZSBvcmlnaW5hbCBzdHVkeSBbaGVyZV0oaHR0cHM6Ly9vc2YuaW8vZWJ4bmYvKSkuIE9wZW4gYGdoYXNlbWlfYnJpZ2h0bmVzc19leHA0LmNzdmAgZmlsZSBhbmQgYW5zd2VyIHRvIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb25zOgoKMS4gSG93IG1hbnkgcGFydGljaXBhbnRzIGRpZCB3ZSB0ZXN0IGluIHRvdGFsPwoyLiBGaW5kIG91dCBob3cgbWFueSBtYWxlIGFuZCBmZW1hbGUgd2UgdGVzdGVkLgozLiBDYWxjdWxhdGUgbWVhbiBhbmQgc2QgZm9yIGFnZSBhbmQgY29nbml0aXZlIGFiaWxpdHkgKGBhaDRgKS4KCgpgYGB7ciB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0KZ2hhc2VtaV9kYXRhIDwtIHJlYWRfY3N2KGhlcmUoImNsZWFuZWRfZGF0YSIsImdoYXNlbWlfYnJpZ2h0bmVzc19leHA0LmNzdiIpKQoKZ2hhc2VtaV9kYXRhICU+JSBzdW1tYXJpc2UobiA9IG5fZGlzdGluY3QocGFydGljaXBhbnQpKSAjIG51bWJlciBvZiBwYXJ0aWNpcGFudHM6MjAwCgpnaGFzZW1pX2RhdGEgJT4lIGdyb3VwX2J5IChwYXJ0aWNpcGFudCkgJT4lIGZpbHRlciAocm93X251bWJlcigpPT0xKSAlPiUgZ3JvdXBfYnkgKGdlbmRlcikgJT4lIHN1bW1hcmlzZShuPSBuKCkpICU+JSB1bmdyb3VwKCkgIyAxODMgZmVtYWxlLCAxNyBtYWxlCgpnaGFzZW1pX2RhdGEgJT4lIGRwbHlyOjpzZWxlY3QgKGFnZSwgYWg0KSAlPiUgc2tpbXI6OnNraW0oKSAjIG1lYW4gYW5kIHNkIGZvciBhZ2UgYW5kIGNvZ25pdGl2ZSBhYmlsaXR5CmBgYAoKCiMgRGF0YSBWaXN1YWxpemF0aW9uCgpGaXJzdCwgd2UgbmVlZCB0byBjcmVhdGUgYSBkYXRhc2V0IHdpdGggYWdncmVnYXRlZCBgdHJ1dGggZXN0aW1hdGVgIHNjb3JlcyBvdmVyIGBncm91cGAgYW5kIGBzdGFnZWAuIFdlIHdpbGwgdXNlIHRoaXMgZGF0YXNldCBmb3IgbGluZSBhbmQgYmFyIGdyYXBocy4KCmBgYHtyIG1lc3NhZ2U9Riwgd2FybmluZz1GLCBkcGk9IDMwMCwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NX0KCmFnZ3JlZ2F0ZWRfZGF0YV9leHAxIDwtIGRhdGFfZXhwMSAlPiUKICBncm91cF9ieShzdGFnZSwgZ3JvdXApICU+JQogIG11dGF0ZSh0cnV0aF9lc3RpbWF0ZSA9IG1lYW4odHJ1dGhfZXN0aW1hdGUpKSAlPiUKICB1bmdyb3VwKCkKCmJhcnBsb3RfZXhwMSA8LSBhZ2dyZWdhdGVkX2RhdGFfZXhwMSAlPiUKICBnZ3Bsb3QoYWVzKHg9c3RhZ2UsIHk9IHRydXRoX2VzdGltYXRlLCBmaWxsPWdyb3VwKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbj0gImRvZGdlIikrCiAgIyBzdGF0X3N1bW1hcnkoZnVuPSBtZWFuLCBnZW9tID0gImJhciIsIHBvc2l0aW9uID0gImRvZGdlIikrICMgY2FuIGJlIHVzZWQgaW5zdGVhZCBvZiBnZW9tX2JhcigpIGZvciBsb25nIGRhdGFmcmFtZXMKICBsYWJzICh4PSAnJywgeT0gIlRydXRoIExpa2VsaWhob2QgRXN0aW1hdGUiKSArIAogIHRoZW1lX2J3KCkgKyAKICBzY2FsZV9maWxsX2phbWEoKSAKCmJhcnBsb3RfZXhwMQoKCmJhcnBsb3RfZmFjZXRfZXhwMSA8LSBhZ2dyZWdhdGVkX2RhdGFfZXhwMSAlPiUKICBnZ3Bsb3QoYWVzKHg9Z3JvdXAsIHk9IHRydXRoX2VzdGltYXRlLCBmaWxsPXN0YWdlKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbj0gImRvZGdlIikrCiAgbGFicyAoeD0gJycsIHk9ICJUcnV0aCBMaWtlbGloaG9kIEVzdGltYXRlIikgKyAKICB0aGVtZV9idygpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgIGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMSksCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpKSArCiAgZmFjZXRfd3JhcCh+c3RhZ2UpKwogIHNjYWxlX2ZpbGxfamNvKCkgCgpiYXJwbG90X2ZhY2V0X2V4cDEKCgpsaW5lcGxvdF9leHAxIDwtIGFnZ3JlZ2F0ZWRfZGF0YV9leHAxICU+JQogIGdncGxvdChhZXMoeD1mYWN0b3Ioc3RhZ2UpLCB5PSB0cnV0aF9lc3RpbWF0ZSwgZ3JvdXA9IGdyb3VwLCBjb2xvcj0gZ3JvdXApKSArCiAgZ2VvbV9saW5lKGFlcyhsaW5ldHlwZT0gZ3JvdXApKSArCiAgZ2VvbV9wb2ludChzaXplPSA1KSsKICBsYWJzICh4PSAnJywgeT0gIlRydXRoIExpa2VsaWhob2QgRXN0aW1hdGUiKSArIAogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTExKSwKICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpICsKICBzY2FsZV9jb2xvcl9uZWptKCkgCgpsaW5lcGxvdF9leHAxCgoKdmlvbGlucGxvdF9leHAxIDwtIGRhdGFfZXhwMSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZmFjdG9yKHN0YWdlKSwgeT0gdHJ1dGhfZXN0aW1hdGUsIGZpbGw9IGdyb3VwKSkgKwogIGdlb21fdmlvbGluKCkrCiAgbGFicyAoeD0gJycsIHk9ICJUcnV0aCBMaWtlbGloaG9kIEVzdGltYXRlIikgKyAKICB0aGVtZV9idygpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTExKSwKICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpICsKICBzY2FsZV9maWxsX2QzKCkgCgp2aW9saW5wbG90X2V4cDEKCgpib3hwbG90X2V4cDEgPC0gZGF0YV9leHAxICU+JQogIGdncGxvdChhZXMoeD1mYWN0b3Ioc3RhZ2UpLCB5PSB0cnV0aF9lc3RpbWF0ZSwgZmlsbD0gZ3JvdXApKSArCiAgZ2VvbV9ib3hwbG90KCkrCiAgI2dlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjc1KSwgYWxwaGE9IC41KSsKICBsYWJzICh4PSAnJywgeT0gIlRydXRoIExpa2VsaWhob2QgRXN0aW1hdGUiKSArIAogIHRoZW1lX2J3KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICBheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTEpLAogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSkgKwogIHNjYWxlX2ZpbGxfc2ltcHNvbnMoKSAKCmJveHBsb3RfZXhwMQoKCmJveHBsb3RfZmFjZXRfZXhwMSA8LSBkYXRhX2V4cDEgJT4lCiAgZ2dwbG90KGFlcyh4PWZhY3RvcihzdGFnZSksIHk9IHRydXRoX2VzdGltYXRlLCBmaWxsPSBncm91cCkpICsKICBnZW9tX2JveHBsb3QoKSsKICBsYWJzICh4PSAnJywgeT0gIlRydXRoIExpa2VsaWhob2QgRXN0aW1hdGUiKSArIAogIHRoZW1lX2J3KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICBheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTEpLAogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpICsKICBmYWNldF93cmFwKH5ncm91cCkrCiAgc2NhbGVfY29sb3Jfc2ltcHNvbnMoKSAKCmJveHBsb3RfZmFjZXRfZXhwMQoKCmBgYAoKSG93IHRvIGNvbWJpbmUgbXVsdGlwbGUgcGxvdHM/IFdlIGNhbiB1c2UgdGhlIGBwYXRjaHdvcmtgIHBhY2thZ2UuIEEgbmljZSB0dXRvcmlhbCBvbiB1c2luZyB0aGlzIHBhY2thZ2UgY2FuIGJlIGZvdW5kIFtoZXJlXShodHRwczovL3BhdGNod29yay5kYXRhLWltYWdpbmlzdC5jb20vYXJ0aWNsZXMvcGF0Y2h3b3JrLmh0bWwpCmBgYHtyIGRwaT0gMzAwLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD05fQoKY29tYmluZWRfcGxvdF9leHAxIDwtIChiYXJwbG90X2ZhY2V0X2V4cDErbGluZXBsb3RfZXhwMSkgLyAodmlvbGlucGxvdF9leHAxK2JveHBsb3RfZXhwMSkKY29tYmluZWRfcGxvdF9leHAxCmBgYAoKSG93IHRvIHNhdmUgYSBwbG90PwpgYGB7cm1lc3NhZ2U9Rn0KZ2dzYXZlKGNvbWJpbmVkX3Bsb3RfZXhwMSwgZmlsZW5hbWUgPSBoZXJlKCJvdXRwdXRzIiwiY29tYmluZWRfcGxvdF9leHAxLnBuZyIpLCBkcGk9MzAwKQpgYGAKCiMgRGF0YSBBbmFseXNpcwoKCiMjIHQtdGVzdAoKSXMgdGhlcmUgYSBkaWZmZXJlbmNlIGJldHdlZW4gZ3JvdXBzIGF0IHRoZSBmaXJzdCBzdGFnZT8gSWRlYWxseSwgd2Ugd2FudCBwYXJ0aWNpcGFudHMnIHJhdGluZ3MgYXQgdGhlIGZpcnN0IHN0YWdlIGJlIHNpbWlsYXIgZm9yIGJvdGggZ3JvdXBzIGJlY2F1c2Ugd2UgaGF2ZSBub3QgZG9uZSBhbnkgbWFuaXB1bGF0aW9ucy4gUHJldmlvdXMgZ3JhcGhzIHNob3dlZCB1cyB0aGF0IHJhdGluZ3Mgb2Ygc2ltcGxlIGFuZCBjb21wbGV4IGdyb3VwIGF0IHRoaXMgc3RhZ2UgYXJlIHByZXR0eSBjbG9zZS4gTGV0J3MgdGVzdCB0aGF0IHVzaW5nIGFuICoqaW5kZXBlbmRlbnQgdC10ZXN0KiogKGJlY2F1c2Ugd2UgaGF2ZSAyIGluZGVwZW5kZW50IGdyb3Vwcyk6CgpgYGB7cn0KIyBJcyB0aGVyZSBhIGRpZmZlcmVuY2UgYmV0d2VlbiBncm91cHMgYXQgdGhlIGZpcnN0IHN0YWdlPwpkYXRhX2V4cDEgJT4lIAogIGdyb3VwX2J5KGdyb3VwKSAlPiUgCiAgZmlsdGVyKHN0YWdlPT0nc3RhZ2UxJykgJT4lIAogIHVuZ3JvdXAgKCkgJT4lCiAgdC50ZXN0KHRydXRoX2VzdGltYXRlfmdyb3VwLCBkYXRhID0gLiwgcGFpcmVkPUZBTFNFKQpgYGAKCk5vdywgd2Ugd29uZGVyIGlmIG9wcG9zaW5nIGFyZ3VtZW50cyB3ZXJlIGVmZmVjdGl2ZSBhdCBhbGwsIHJlZ2FyZGxlc3Mgb2YgcGFydGljaXBhbnRzJyBncm91cC4gU28sIHdlIHdvdWxkIGxpa2UgdG8gdGVzdCBpZiByYXRpbmdzIGF0IHRoZSBmaW5hbCBzdGFnZSBhcmUgbG93ZXIgdGhhbiByYXRpbmdzIGF0IHRoZSBzdGFnZSA0PyBTaW5jZSBhIHBhaXIgb2Ygc2NvcmUgYXQgc3RhZ2UgNCBhbmQgc3RhZ2UgNyBpcyBjb21pbmcgZnJvbSBhIHNhbWUgcGVyc29uLCB3ZSB1c2UgKipwYWlyZWQgdC10ZXN0KiouCgpgYGB7cn0KIyBJcyB0aGVyZSBhIGRpZmZlcmVuY2UgYmV0d2VlbiByYXRpbmdzIG9mIHN0YWdlNCBhbmQgc3RhZ2U3PwpkYXRhX2V4cDEgJT4lIAogIGZpbHRlcihzdGFnZT09J3N0YWdlNCcgfCBzdGFnZT09J3N0YWdlNycpICU+JSAKICB1bmdyb3VwICgpICU+JQogIHQudGVzdCh0cnV0aF9lc3RpbWF0ZX5zdGFnZSwgZGF0YSA9IC4sIHBhaXJlZD1UUlVFKQpgYGAKCgojIyMgRXhlcmNpc2UKCkpvaG4gZXQgYWwuICgyMDE5KSBpbnZlc3RpZ2F0ZWQgdGhlIGNvbnNlcXVlbmNlcyBvZiBiYWNraW5nIGRvd24gKGNoYW5naW5nIG9uZSdzIG1pbmQgaW4gbGlnaHRzIG9mIGV2aWRlbmNlKWFuZCBob3cgb3RoZXIgcGVvcGxlIHZpZXcgc29tZW9uZSB3aG8gY2hhbmdlIHRoZWlyIG1pbmQuIEluIHRoZWlyIHNlY29uZCBleHBlcmltZW50cywgdGhleSBwcmVzZW50ZWQgcGFydGljaXBhbnRzIGVpdGhlciB3aXRoIGEgcGVyc29uIHdobyBjaGFuZ2VzIHRoZWlyIG1pbmQgb3IgYSBwZXJzb24gd2hvIHJlZnVzZXMgdG8gYmFjayBkb3duLiBUaGVuLCB0aGV5IGFza2VkIHBhcnRpY2lwYW50cyB0byByYXRlIGhvdyBpbnRlbGxpZ2VudCBhbmQgY29uZmlkZW50IHRoZSBwZXJzb24gaXMgKFNlZSB0aGUgb3JpZ2luYWwgc3R1ZHkgW2hlcmVdKGh0dHBzOi8vd3d3Lmhicy5lZHUvZmFjdWx0eS9QdWJsaWNhdGlvbiUyMEZpbGVzL0pvaG4lMjBldCUyMGFsJTIwLSUyMHNlbGYtcHJlc2VudGF0aW9uYWwlMjBjb25zZXF1ZW5jZXNfYjg1YjJjNDMtYTViNS00NzRjLTllMmMtZTk4NTNiMTA3MjdlLnBkZikpLiBUaGV5IHJlcG9ydGVkIHRoYXQ6IAoKPiAiUmVsYXRpdmUgdG8gdGhlIGVudHJlcHJlbmV1ciB3aG8gZGlkIG5vdCBiYWNrIGRvd24sIHBhcnRpY2lwYW50cyBqdWRnZWQgdGhlIGVudHJlcHJlbmV1ciB3aG8gYmFja2VkIGRvd24gYXMgbW9yZSBpbnRlbGxpZ2VudCAoTV9iYWNrZWRfZG93bj01LjEzIG91dCBvZiA3LCBTRD0xLjA5OyBNX2RpZF9ub3RfYmFja19kb3duPTMuOTcsIFNEPTEuNTQ7IHQoMjcxLjEyKT3iiJI3LjU5LCBwIDwgLjAwMSkgYnV0IGxlc3MgY29uZmlkZW50IChNX2JhY2tlZF9kb3duPTQuNTAgb3V0IG9mIDcsIFNEPTEuMzY7IE1fZGlkX25vdF9iYWNrX2Rvd249NS42NSwgU0Q9MS4xMDsgdCgyOTEuMDEpPTguMDgsIHAgPCAuMDAxKS4iLgoKT3BlbiB0aGUgYGpvaG5fYmFja2Rvd25fZXhwMi5jc3ZgIGZpbGUgYW5kIHRyeSB0byByZXByb2R1Y2UgdGhlaXIgcmVzdWx0cy4gUnVuIHR3byBzZXBhcmF0ZSBpbmRlcGVuZGVudCB0LXRlc3QsIG9uZSB3aXRoIGBpbnRlbGxpZ2VudGAgYXMgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgb25lIHdpdGggYGNvbmZpZGVudGAgYXMgdGhlIGRlcGVuZGVudCB2YXJpYWJsZS4gRm9yIGJvdGggdC10ZXN0LCB1c2UgYGJhY2tfZG93bmAgYXMgdGhlIGJldHdlZW4tc3ViamVjdCBpbmRlcGVuZGVudCB2YXJpYWJsZS4KCmBgYHtyIG1lc3NhZ2U9Riwgd2FybmluZz1GfQpqb2huX2RhdGEgPC0gcmVhZF9jc3YoaGVyZSgiY2xlYW5lZF9kYXRhIiwiam9obl9iYWNrZG93bl9leHAyLmNzdiIpKQoKCnQudGVzdChpbnRlbGxpZ2VudH5iYWNrX2Rvd24sIGRhdGEgPSBqb2huX2RhdGEsIHBhaXJlZD1GQUxTRSkKdC50ZXN0KGNvbmZpZGVudH5iYWNrX2Rvd24sIGRhdGEgPSBqb2huX2RhdGEsIHBhaXJlZD1GQUxTRSkKYGBgCgoKIyMgQW5hbHlzaXMgb2YgVmFyaWFuY2UgKEFOT1ZBKQoKTm93LCBsZXQncyBhbnN3ZXIgb3VyIG1haW4gcXVlc3Rpb246IERvIHBhcnRpY2lwYW50cyBpbiB0aGUgc2ltcGxlIGdyb3VwIHNob3cgaGlnaGVyIHJhdGluZ3MgZm9yIHN1cHBvcnRpdmUgYXJndW1lbnRzIChzdGFnZSAyIHRvIDQpIGFuZCBsb3dlciByYXRpbmdzIGZvciBvcHBvc2luZyBhcmd1bWVudHMgKHN0YWdlIDUgdG8gNyksIGNvbXBhcmVkIHRvIHBhcnRpY2lwYW50cyBpbiB0aGUgY29tcGxleCBncm91cD8gSWYgdGhpcyBpcyB0aGUgY2FzZS4gd2UgZXhwZWN0IGFuIGludGVyYWN0aW9uIGluIHRoZSB0cmFkaXRpb25hbCAqKkFuYWx5c2lzIG9mIFZhcmlhbmNlIChBT05WQSkqKiB0ZXN0LgoKYGBge3IgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CmFvdl9tMSA8LSBhb3ZfY2FyICh0cnV0aF9lc3RpbWF0ZSB+IGdyb3VwKnN0YWdlICsKICAgICAgICAgICAgICAgICAgICAgRXJyb3Ioc3ViamVjdC9zdGFnZSksIGRhdGEgPSBkYXRhX2V4cDEpCmBgYAoKYGBge3IgZWNobz1GfQprbml0cjo6a2FibGUobmljZShhb3ZfbTEpKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJib3JkZXJlZCIsICJjb25kZW5zZWQiKSwgZml4ZWRfdGhlYWQgPSBULCBmdWxsX3dpZHRoID0gVCkKYGBgCgpBcyB5b3UgY2FuIHNlZSwgd2UgZm91bmQgYSBzaWduaWZpY2FudCBtYWluIGVmZmVjdCBvZiBzdGFnZSBhbmQgYSBzaWduaWZpY2FudCBncm91cCBieSBzdGFnZSBpbnRlcmFjdGlvbi4gV2UgY2FuIHVzZSB0aGUgYGVtbWVhbnNgIHBhY2thZ2UgdG8gZG8gcG9zdC1ob2MgdGVzdHMuCgpgYGB7ciB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0KIyBtYWluIGVmZmVjdCBvZiBzdGFnZQplbW1lYW5zKGFvdl9tMSwgJ3N0YWdlJykKcGFpcnMoZW1tZWFucyhhb3ZfbTEsICdzdGFnZScpLCBhZGp1c3Q9ICdob2xtJykKYGBgCgoKYGBge3Igd2FybmluZz1GLCBtZXNzYWdlPUZ9CiMgZ3JvdXAgYnkgc3RhZ2UgaW50ZXJhY3Rpb24KZW1tZWFucyhhb3ZfbTEsICJncm91cCIsIGJ5PSAic3RhZ2UiKQp1cGRhdGUocGFpcnMoZW1tZWFucyhhb3ZfbTEsICJncm91cCIsIGJ5PSAic3RhZ2UiKSksIGJ5ID0gTlVMTCwgYWRqdXN0ID0gImhvbG0iKSAKYGBgCgpZb3UgY2FuIHVzZSB0aGUgYGFmZXhfcGxvdGAgZnVuY3Rpb24gZnJvbSBhZmV4IHRvIGNyZWF0ZSBiZWF1dGlmdWwgcGxvdHMuIFRob3NlIHBsb3RzIGludGVyYWN0cyBuaWNlbHkgd2l0aCBnZ3Bsb3Q6CmBgYHtyIG1lc3NhZ2U9Riwgd2FybmluZz1GLCBkcGk9IDMwMH0KYWZleF9wbG90KGFvdl9tMSwgeCA9ICJzdGFnZSIsIHRyYWNlID0gImdyb3VwIiwgZXJyb3I9J2JldHdlZW4nLAogICAgICAgICAgbGluZV9hcmcgPSBsaXN0KHNpemU9MSksCiAgICAgICAgICBwb2ludF9hcmcgPSBsaXN0KHNpemU9My41KSwKICAgICAgICAgIGRhdGFfYXJnID0gbGlzdChzaXplPSAxLCBjb2xvcj0gJ2dyZXknLCB3aWR0aD0uNCksCiAgICAgICAgICBkYXRhX2dlb20gPSBnZW9tX2JveHBsb3QsCiAgICAgICAgICBtYXBwaW5nID0gYygibGluZXR5cGUiLCAic2hhcGUiLCAiZmlsbCIpLAogICAgICAgICAgbGVnZW5kX3RpdGxlID0gIkdyb3VwIikgKwogIGxhYnMoeSA9ICJUcnV0aCBMaWtlbGloaG9kIEVzdGltYXRlIiwgeCA9ICIiKSArCiAgdGhlbWVfYncoKSsgIyByZW1vdmUgdGhlIGdyZXkgYmFja2dyb3VuZCBhbmQgZ3JpZAogIHRoZW1lKGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMyksCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEzKSwKICAgICAgICBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTMpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbj0nYm90dG9tJywKICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDEsICJjbSIpLAogICAgICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICdibGFjaycsIGZpbGwgPSAnd2hpdGUnLCBsaW5ldHlwZT0nc29saWQnKSkrCiAgc2NhbGVfY29sb3Jfc2ltcHNvbnMoKSArCiAgc2NhbGVfZmlsbF9zaW1wc29ucygpCmBgYAoKCklmIHlvdSBhcmUgaW50ZXJlc3RlZCBpbiB0aGlzIHRvcGljLCBjaGVjayBvdXQgdGhpcyBuaWNlIHR1dG9yaWFsIGFib3V0IFt1c2luZyBhZmV4IHRvIHJ1biBBTk9WQV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2FmZXgvdmlnbmV0dGVzL2FmZXhfYW5vdmFfZXhhbXBsZS5odG1sKSwgYW5kIGFsc28gdGhpcyBpbnRlcmVzdGluZyB0dXRvcmlhbCBvbiB0aGUgW2VtbWVhbnMgcGFja2FnZV0oaHR0cHM6Ly9hb3NtaXRoLnJiaW5kLmlvLzIwMTkvMDMvMjUvZ2V0dGluZy1zdGFydGVkLXdpdGgtZW1tZWFucy8pLgoKIyMjIEV4ZXJjaXNlCgpSb3RlbGxvIGV0IGFsLiAoMjAxOCkgaW52ZXN0aWdhdGVkIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIHRoZSByYWNlIChXaGl0ZSB2cy4gQmxhY2sgZmFjZXMpIGFuZCB0aGUgZ3VuLXRvb2wganVkZ21lbnRzLiBJbiB0aGVpciBmaXJzdCBleHBlcmltZW50cywgdGhleSBwcmVzZW50ZWQgcGFydGljaXBhbnRzIHdpdGggMTYgV2hpdGUgbWFsZSBmYWNlcyBhbmQgMTYgQmxhY2sgbWFsZSBmYWNlcywgYW5kIGZvbGxvd2luZyB0aGF0IDggaW1hZ2VzIG9mIGd1bnMgYW5kIDggaW1hZ2VzIG9mIHRvb2xzLiBUaGV5IGFza2VkIHBhcnRpY2lwYW50cyB0byBqdWRnZSBpZiB0aGUgb2JqZWN0IGlzIGEgdG9vbCBvciBhIGd1biBieSBwcmVzc2luZyBrZXlib2FyZCBidXR0b25zLiBUaGVuLCB0aGV5IHJhbiBhbiBBTk9WQSB0byBzZWUgaWYgcGFydGljaXBhbnRzJyBndW4gcmVzcG9uc2VzIGFyZSBoaWdoZXIgZm9yIGFueSBvZiB0aGUgcmFjZXMuIFNvLCB0aGV5IGluY2x1ZGVkIHByaW1lIHJhY2UgKEJsYWNrLCBXaGl0ZSkgYW5kIHRhcmdldCBpZGVudGl0eSAoZ3VuLCB0b29sKSBhcyBpbmRlcGVuZGVudCB2YXJpYWJsZXMgYW5kIHBhcnRpY2lwYW50cycgZ3VuIHJlc3BvbnNlcyBhcyBkZXBlbmRlbnQgdmFyaWFibGUgaW50byB0aGVpciBsaW5lYXIgbW9kZWwgKFNlZSB0aGUgb3JpZ2luYWwgc3R1ZHkgW2hlcmVdKGh0dHBzOi8vcHN5YXJ4aXYuY29tL2E3azk2KSkuIFRoZXkgZm91bmQgdGhhdDogCgo+ICJQYXJ0aWNpcGFudHMgbWFkZSBtb3JlIGd1biByZXNwb25zZXMgdG8gZ3VucyB0aGFuIHRvIHRvb2xzLCBGKDEsNDUpID0gNTMyNDMsIHAgPCAwLjAwMDEsIM63MmcgPSAwLjk5OC4gSG93ZXZlciwgdGhlIHJhY2Ugb2YgdGhlIHByaW1lIGZhY2UgZGlkIG5vdCBtYXR0ZXIsIEYoMSw0NSkgPSAwLjI4NywgcCA+IDAuNTksIM63MmcgPSAwLjAwMSwgbm9yIHdhcyB0aGVyZSBhbiBpbnRlcmFjdGlvbiBvZiBwcmltZSByYWNlIHdpdGggdGFyZ2V0IG9iamVjdCwgRigxLDQ1KSA9IDAuMDIyLCBwID4gMC44OCwgzrcyZyA9IDAuMDAwKSIuCgpPcGVuIHRoZSBgcm90ZWxsb19zaG9vdGVyX2V4cDEuY3N2YCBmaWxlIGFuZCB0cnkgdG8gcmVwcm9kdWNlIHRoZWlyIHJlc3VsdHMuIFJ1biBhbiBBTk9WQSAodHlwZSBJSUkpIHdpdGggYHJlc3BgIGFzIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIHRhcmdldCwgcHJpbWUsIGFuZCB0aGVpciBpbnRlcmFjdGlvbiBhcyBpbmRlcGVuZGVudCB2YXJpYWJsZXMuCgoKYGBge3IgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CiMgbG9hZCB0aGUgZ2VuZXJhbCBkYXRhIGZpbGUKcm90ZWxsb19kYXRhIDwtIHJlYWRfY3N2KGhlcmUoImNsZWFuZWRfZGF0YSIsInJvdGVsbG9fc2hvb3Rlcl9leHAxLmNzdiIpKQoKIyBBTk9WQQpyb3RlbGxvX2FvdiA8LSBhb3ZfY2FyIChyZXNwIH4gdGFyZ2V0KnByaW1lICsKICAgICAgICAgICBFcnJvcihzdWJqZWN0L3RhcmdldCpwcmltZSksIGRhdGEgPSByb3RlbGxvX2RhdGEpCmBgYAoKYGBge3IgZWNobz1GfQprbml0cjo6a2FibGUobmljZShyb3RlbGxvX2FvdikpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImJvcmRlcmVkIiwgImNvbmRlbnNlZCIpLCBmaXhlZF90aGVhZCA9IFQsIGZ1bGxfd2lkdGggPSBUKQpgYGAKCgoKIyMgQ29ycmVsYXRpb24KCk5vdywgbGV0J3MgYW5zd2VyIHRvIGFub3RoZXIgcXVlc3Rpb24gb2YgdGhpcyBzdHVkeTogZG9lcyBwZXJzdWFzaW9uIGFuZCBkaXNzdWFzaW9uIGlzIHJlbGF0ZWQgdG8gb3Blbi1taW5kZWRuZXNzLCBjb2duaXRpdmUgYWJpbGl0eSwgcmVhc29uaW5nIGFiaWxpdGllcywgYW5kIGNvZ25pdGl2ZSBzdHlsZT8gVG8gYW5zd2VyIHRoaXMgcXVlc3Rpb24sIHdlIG5lZWQgdG8gY3JlYXRlIHR3byBpbmRleGVzIChzY29yZXMpIG9uZSBmb3IgcGVyc3Vhc2lvbiBhbmQgb25lIGZvciBkaXNzdWFzaW9uLiBUaGVuIHdlIGNhbiBkbyBhIGNvcnJlbGF0aW9uIHRlc3Q6CgpgYGB7ciBtZXNzYWdlPUYsIGV2YWw9RiwgZmlnLmFsaWduPSdjZW50ZXInLCBkcGk9MzAwfQpjb3JfZGF0YV9leHAxIDwtIGRhdGFfZXhwMSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YWdlLCB2YWx1ZXNfZnJvbSA9IHRydXRoX2VzdGltYXRlKSAlPiUKICBncm91cF9ieShzdWJqZWN0KSAlPiUKICBtdXRhdGUocGVyc3Vhc2lvbl9pbmRleD0gc3RhZ2UyKyBzdGFnZTMrIHN0YWdlNCAtIHN0YWdlMSwKICAgICAgICAgZGlzc3Vhc2lvbl9pbmRleD0gKDEwMS1zdGFnZTUpICsgKDEwMS1zdGFnZTYpICsgKDEwMS1zdGFnZTcpIC0gKDEwMS1zdGFnZTQpKSAlPiUKICB1bmdyb3VwKCklPiUKICBkcGx5cjo6c2VsZWN0KHBlcnN1YXNpb25faW5kZXgsZGlzc3Vhc2lvbl9pbmRleCxhb3RlX3RvdGFsLG51bWVyYWN5X3RvdGFsLGNydF90b3RhbCxtaW5kd2FyZV90b3RhbCkKCiMtLS0tLS0tLS0tIEJhc2UgUjoKY29yKGNvcl9kYXRhX2V4cDEsIG1ldGhvZCA9ICJwZWFyc29uIiwgIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQoKIy0tLS0tLS0tLS0gUHN5Y2ggbGlicmFyeToKY29yX2RhdGFfZXhwMSAlPiUgCiAgcHN5Y2g6OnBhaXJzLnBhbmVscyhtZXRob2QgPSAicGVhcnNvbiIsIGhpc3QuY29sID0gIiMwMEFGQkIiLCBkZW5zaXR5ID0gVCwgZWxsaXBzZXMgPSBGLCBzdGFycyA9IFQpCgojLS0tLS0tLS0tLSBDb3JyZWxhdGlvbiBsaWJyYXJ5Ogpjb3JyZWxhdGlvbjo6Y29ycmVsYXRpb24oY29yX2RhdGFfZXhwMSkgJT4lIHN1bW1hcnkoKQoKIy0tLS0tLS0tLS0gYXBhVGFibGVzIGxpYnJhcnk6CmNvcl9kYXRhX2V4cDEgJT4lIAogIGFwYVRhYmxlczo6YXBhLmNvci50YWJsZShmaWxlbmFtZT0iLi9vdXRwdXRzL0Nvck1hdHJpeC5kb2MiLCBzaG93LmNvbmYuaW50ZXJ2YWw9VCkKYGBgCgpgYGB7ciBtZXNzYWdlPUYsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLCBkcGk9MzAwfQpjb3JfZGF0YV9leHAxIDwtIGRhdGFfZXhwMSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YWdlLCB2YWx1ZXNfZnJvbSA9IHRydXRoX2VzdGltYXRlKSAlPiUKICBncm91cF9ieShzdWJqZWN0KSAlPiUKICBtdXRhdGUocGVyc3Vhc2lvbl9pbmRleD0gc3RhZ2UyKyBzdGFnZTMrIHN0YWdlNCAtIHN0YWdlMSwKICAgICAgICAgZGlzc3Vhc2lvbl9pbmRleD0gKDEwMS1zdGFnZTUpICsgKDEwMS1zdGFnZTYpICsgKDEwMS1zdGFnZTcpIC0gKDEwMS1zdGFnZTQpKSAlPiUKICB1bmdyb3VwKCklPiUKICBkcGx5cjo6c2VsZWN0KHBlcnN1YXNpb25faW5kZXgsZGlzc3Vhc2lvbl9pbmRleCxhb3RlX3RvdGFsLG51bWVyYWN5X3RvdGFsLGNydF90b3RhbCxtaW5kd2FyZV90b3RhbCkKCiMtLS0tLS0tLS0tIEJhc2UgUjoKY29yKGNvcl9kYXRhX2V4cDEsIG1ldGhvZCA9ICJwZWFyc29uIiwgIHVzZSA9ICJjb21wbGV0ZS5vYnMiKSU+JQogIGtuaXRyOjprYWJsZShkaWdpdHMgPSAyKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJib3JkZXJlZCIsICJjb25kZW5zZWQiKSwgZml4ZWRfdGhlYWQgPSBULCBmdWxsX3dpZHRoID0gRiklPiUKICBzY3JvbGxfYm94KHdpZHRoID0gIjc4MHB4IikKCiMtLS0tLS0tLS0tIFBzeWNoIGxpYnJhcnk6CmNvcl9kYXRhX2V4cDEgJT4lIAogIHBzeWNoOjpwYWlycy5wYW5lbHMobWV0aG9kID0gInBlYXJzb24iLCBoaXN0LmNvbCA9ICIjMDBBRkJCIiwgZGVuc2l0eSA9IFQsIGVsbGlwc2VzID0gRiwgc3RhcnMgPSBUKQoKIy0tLS0tLS0tLS0gQ29ycmVsYXRpb24gbGlicmFyeToKY29ycmVsYXRpb246OmNvcnJlbGF0aW9uKGNvcl9kYXRhX2V4cDEpICU+JSBzdW1tYXJ5KCklPiUKICBrbml0cjo6a2FibGUoZGlnaXRzID0gMikgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiYm9yZGVyZWQiLCAiY29uZGVuc2VkIiksIGZpeGVkX3RoZWFkID0gVCwgZnVsbF93aWR0aCA9IEYpJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICI3ODBweCIpCgpgYGAKCgoKIyMjIEV4ZXJjaXNlCgpQZW5ueWNvb2sgZXQgYWwuICgyMDIwKSBpbnZlc3RpZ2F0ZWQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGFjdGl2ZWx5IG9wZW4tbWluZGVkIHRoaW5raW5nIHN0eWxlIGFib3V0IGV2aWRlbmNlIChBT1QtRSkgYW5kIGRpZmZlcmVudCBwb2xpdGljYWwsIHNjaWVudGlmaWMsIGFuZCByZWxpZ2lvdXMgYmVsaWVmcyAoc2VlIHRoZSBvcmlnaW5hbCBwYXBlciBbaGVyZV0oaHR0cHM6Ly9wc3lhcnhpdi5jb20vYTdrOTYpKS4gSW4gdGhlaXIgZmlyc3QgZXhwZXJpbWVudCwgdGhleSBjYWxjdWxhdGVkIHRoZSBjb3JyZWxhdGlvbiBvZiBBT1RFIGFuZCBzY2llbnRpZmljIGJlbGllZnMgaXRlbXMgKGdsb2JhbCB3YXJtaW5nLCBldm9sdXRpb24sIGV0Yy4pIGFuZCB0aGV5IGZvdW5kIHRoZSBmb2xsb3dpbmcgcmVzdWx0czoKCmBgYHtyIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNzAwcHgiLCBvdXQuaGVpZ2h0PSIzNTBweCIsIGZpZy5jYXA9ICJhZGFwdGVkIGZyb20gW1Blbm55Y29vayBldCBhbC4gKDIwMjApXShodHRwczovL3BzeWFyeGl2LmNvbS9hN2s5NikifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlKCdpbnB1dHMnLCdwZW5ueWNvb2tfY29yci5wbmcnKSkKYGBgCgpPcGVuIHRoZSBgcGVubnljb29rX2FvdGVfZXhwMS5jc3ZgIGZpbGUgYW5kIHRyeSB0byByZXByb2R1Y2UgdGhlaXIgcmVzdWx0cyBieSBjcmVhdGluZyB0aGUgc2FtZSBjb3JyZWxhdGlvbiBtYXRyaXguCgpgYGB7ciBtZXNzYWdlPUYsIGV2YWw9Rn0KcGVubnljb29rX2RhdGEgPC0gcmVhZF9jc3YoaGVyZSgiY2xlYW5lZF9kYXRhIiwicGVubnljb29rX2FvdGVfZXhwMS5jc3YiKSkgCgoKIy0tLS0tLS0tLS0gQmFzZSBSOgpjb3IocGVubnljb29rX2RhdGEsIG1ldGhvZCA9ICJwZWFyc29uIiwgIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQoKIy0tLS0tLS0tLS0gUHN5Y2ggbGlicmFyeToKcGVubnljb29rX2RhdGEgJT4lIAogIHBzeWNoOjpwYWlycy5wYW5lbHMobWV0aG9kID0gInBlYXJzb24iLCBoaXN0LmNvbCA9ICIjMDBBRkJCIiwgZGVuc2l0eSA9IFQsIGVsbGlwc2VzID0gRiwgc3RhcnMgPSBUKQoKIy0tLS0tLS0tLS0gQ29ycmVsYXRpb24gbGlicmFyeToKY29ycmVsYXRpb246OmNvcnJlbGF0aW9uKHBlbm55Y29va19kYXRhKSAlPiUgc3VtbWFyeSgpCgojLS0tLS0tLS0tLSBhcGFUYWJsZXMgbGlicmFyeToKcGVubnljb29rX2RhdGEgJT4lIAogIGFwYVRhYmxlczo6YXBhLmNvci50YWJsZShmaWxlbmFtZT0iLi9vdXRwdXRzL0Nvck1hdHJpeC5kb2MiLCBzaG93LmNvbmYuaW50ZXJ2YWw9VCkKYGBgCgoKYGBge3IgbWVzc2FnZT1GLCBldmFsPVQsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLCBkcGk9MzAwfQpwZW5ueWNvb2tfZGF0YSA8LSByZWFkX2NzdihoZXJlKCJjbGVhbmVkX2RhdGEiLCJwZW5ueWNvb2tfYW90ZV9leHAxLmNzdiIpKSAlPiUKICBjbGVhbl9uYW1lcygpCgpjb3JyZWxhdGlvbjo6Y29ycmVsYXRpb24ocGVubnljb29rX2RhdGEpICU+JSBzdW1tYXJ5KCkgJT4lCiAga25pdHI6OmthYmxlKGRpZ2l0cyA9IDIpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImJvcmRlcmVkIiwgImNvbmRlbnNlZCIpLCBmaXhlZF90aGVhZCA9IFQsIGZ1bGxfd2lkdGggPSBGKSU+JQogIHNjcm9sbF9ib3god2lkdGggPSAiNzgwcHgiKQoKYGBgCgoKIyMgTGluZWFyIFJlZ3Jlc3Npb24KCkluIHRoZSBwcmV2aW91cyBzZWN0aW9uLCB3ZSBmb3VuZCB0aGF0IG9wZW4tbWluZGVkbmVzcyAoQU9ULUUpIGlzIGNvcnJlbGF0ZWQgd2l0aCBwZXJzdWFzaW9uLiBOb3csIG9uZSBtYXkgYXNrIGlmIG9wZW4tbWluZGVkbmVzcyBjYW4gcHJlZGljdCBwZXJzdWFzaW9uIGFmdGVyIGNvbnRyb2xsaW5nIGZvciByZWFzb25pbmcgYW5kIGNvbnRyb2xsaW5nIGFiaWxpdGllcz8gVG8gYW5zd2VyIHRoYXQsIHdlIGNhbiBydW4gYSBtdWx0aXBsZSByZWdyZXNzaW9uIGFuYWx5c2lzOgpgYGB7cn0KZXhwMV9yZWc9bG0ocGVyc3Vhc2lvbl9pbmRleCB+IGFvdGVfdG90YWwrIG51bWVyYWN5X3RvdGFsKyBjcnRfdG90YWwrIG1pbmR3YXJlX3RvdGFsLAogICAgICAgICAgICAgICAgICBkYXRhPWNvcl9kYXRhX2V4cDEpCmBgYAoKYGBge3IgbWVzc2FnZT1GLCBldmFsPVQsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLCBkcGk9MzAwfQpicm9vbTo6dGlkeShleHAxX3JlZyklPiUKICBrbml0cjo6a2FibGUoZGlnaXRzID0gMikgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiYm9yZGVyZWQiLCAiY29uZGVuc2VkIiksIGZpeGVkX3RoZWFkID0gVCwgZnVsbF93aWR0aCA9IFQpCmBgYAoKIyMjIEV4ZXJjaXNlCgpUcsOpbW9sacOocmUgYW5kIERqZXJpb3VhdCAoMjAyMCkgZXhhbWluZWQgdGhlIHJvbGUgb2YgKmNvZ25pdGl2ZSByZWZsZWN0aW9uKiBhbmQgKmJlbGllZiBpbiBzY2llbmNlKiBpbiBjbGltYXRlIGNoYW5nZSBza2VwdGljaXNtLiBJbiB0aGVpciBmaXJzdCBzdHVkeSwgdGhleSByZXZlYWxlZCB0aGF0IGNvZ25pdGl2ZSByZWZsZWN0aW9uIGFuZCBiZWxpZWYgaW4gc2NpZW5jZSBuZWdldGl2ZWx5IHByZWRpY3RlZCBjbGltYXRlIGNoYW5nZSBza2VwdGljaXNtIGV2ZW4gYWZ0ZXIgY29udHJvbGxpbmcgZm9yIGRlbW9ncmFwaGljIGFuZCBjb2duaXRpdmUgYWJpbGl0eSB2YXJpYWJsZXMgKHNlZSB0aGUgb3JpZ2luYWwgcGFwZXIgW2hlcmVdKGh0dHBzOi8vcHN5YXJ4aXYuY29tL3ZwOGs2LykpLiAKCmBgYHtyIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNzAwcHgiLCBvdXQuaGVpZ2h0PSIzNTBweCIsIGZpZy5jYXA9ICJhZGFwdGVkIGZyb20gW1Ryw6ltb2xpw6hyZSBhbmQgRGplcmlvdWF0ICgyMDIwKV0oaHR0cHM6Ly9wc3lhcnhpdi5jb20vdnA4azYvKSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmUoJ2lucHV0cycsJ3RyZW1vbGllcmVfcmVnLnBuZycpKQpgYGAKCk9wZW4gdGhlIGB0cmVtb2xpZXJlX2RhdGFfZXhwMS5jc3ZgIGZpbGUgYW5kIHRyeSB0byByZXByb2R1Y2UgdGhlaXIgcmVzdWx0cyBieSBydW5uaW5nIGEgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24uIEVudGVyIGFnZSwgZ2VuZGVyLCBlZHVjYXRpb24sIGJlbGllZiBpbiBzY2llbmNlLCBsaXRlcmFjeSwgbnVtZXJhY3kgKE51bXRvdGFsKSwgYW5kIGNvZ25pdGl2ZSByZWZsZWN0aW9uIGFzIHByZWRpY3RvcnMgYW5kIGVudGVyIGNsaW1hdGUgY2hhbmdlIHNrZXB0aWNpc20gKGNsaW1hdG8pIGFzIHRoZSBvdXRjb21lIHZhcmlhYmxlLgoKYGBge3IgbWVzc2FnZT1GfQpUcmVtb2xpZXJlX2RhdGEgPC0gcmVhZF9jc3YoaGVyZSgiY2xlYW5lZF9kYXRhIiwidHJlbW9saWVyZV9kYXRhX2V4cDEuY3N2IikpCgpUcmVtb2xpZXJlX3JlZz1sbShDbGltYXRvIH4gQWdlKyBHZW5kZXIrIEVkdWNhdGlvbisgQmVsaWVmSW5TY2llbmNldG90YWwrIExpdGVyYWN5KyBOdW10b3RhbCsgQ29nbml0aXZlUmVmbGVjdGlvbiwKICAgICAgICAgICAgICAgICAgICBkYXRhPVRyZW1vbGllcmVfZGF0YSkKYGBgCgoKYGBge3IgbWVzc2FnZT1GLCBldmFsPVQsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLCBkcGk9MzAwfQpicm9vbTo6dGlkeShUcmVtb2xpZXJlX3JlZyklPiUKICBrbml0cjo6a2FibGUoZGlnaXRzID0gMikgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiYm9yZGVyZWQiLCAiY29uZGVuc2VkIiksIGZpeGVkX3RoZWFkID0gVCwgZnVsbF93aWR0aCA9IFQpCgpnbGFuY2UoVHJlbW9saWVyZV9yZWcpJT4lCiAga25pdHI6OmthYmxlKGRpZ2l0cyA9IDIpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImJvcmRlcmVkIiwgImNvbmRlbnNlZCIpLCBmaXhlZF90aGVhZCA9IFQsIGZ1bGxfd2lkdGggPSBGKSU+JQogIHNjcm9sbF9ib3god2lkdGggPSAiNzgwcHgiKQpgYGAKCgojIFJtYXJrZG93bgoKVG8gYmUgY29tcGxldGVkLi4uCgoKIyBSZWZlcmVuY2VzCgotIEdoYXNlbWksIE8uLCBIYW5kbGV5LCBTLiwgJiBIb3dhcnRoLCBTLiAoMjAyMCkuIFRoZSBCcmlnaHQgSG9tdW5jdWx1cyBpbiBvdXIgSGVhZDogSW5kaXZpZHVhbCBEaWZmZXJlbmNlcyBpbiBJbnR1aXRpdmUgU2Vuc2l0aXZpdHkgdG8gTG9naWNhbCBWYWxpZGl0eS4KCi0gSm9obiwgTC4gSy4sIEplb25nLCBNLiwgR2lubywgRi4sICYgSHVhbmcsIEwuICgyMDE5KS4gVGhlIHNlbGYtcHJlc2VudGF0aW9uYWwgY29uc2VxdWVuY2VzIG9mIHVwaG9sZGluZyBvbmXigJlzIHN0YW5jZSBpbiBzcGl0ZSBvZiB0aGUgZXZpZGVuY2UuIE9yZ2FuaXphdGlvbmFsIEJlaGF2aW9yIGFuZCBIdW1hbiBEZWNpc2lvbiBQcm9jZXNzZXMsIDE1NCwgMS0xNC4KCi0gUGVubnljb29rLCBHLiwgQ2hleW5lLCBKLiBBLiwgS29laGxlciwgRC4gSi4sICYgRnVnZWxzYW5nLCBKLiBBLiAoMjAyMCkuIE9uIHRoZSBiZWxpZWYgdGhhdCBiZWxpZWZzIHNob3VsZCBjaGFuZ2UgYWNjb3JkaW5nIHRvIGV2aWRlbmNlOiBJbXBsaWNhdGlvbnMgZm9yIGNvbnNwaXJhdG9yaWFsLCBtb3JhbCwgcGFyYW5vcm1hbCwgcG9saXRpY2FsLCByZWxpZ2lvdXMsIGFuZCBzY2llbmNlIGJlbGllZnMuIEp1ZGdtZW50IGFuZCBEZWNpc2lvbiBNYWtpbmcsIDE1KDQpLCA0NzYuCgotIFJvdGVsbG8sIEMuIE0uLCBLZWxseSwgTC4gSi4sIEhlaXQsIEUuLCBWYXppcmUsIFMuLCAmIFZ1bCwgRS4gKDIwMTgpLiBUaGUgU2hhcGUgb2YgUk9DIEN1cnZlcyBpbiBTaG9vdGVyIFRhc2tzOiBJbXBsaWNhdGlvbnMgZm9yIEJlc3QgUHJhY3RpY2VzIGluIEFuYWx5c2lzLiBDb2xsYWJyYTogUHN5Y2hvbG9neSwgNCgxKS4KCi0gVHLDqW1vbGnDqHJlLCBCLiwgJiBEamVyaW91YXQsIEguICgyMDIwKS4gRG9u4oCZdCB5b3Ugc2VlIHRoYXQgaXRzIGNvbGQhIEV4cGxvcmluZyB0aGUgcm9sZXMgb2YgY29nbml0aXZlIHJlZmxlY3Rpb24sIGNsaW1hdGUgc2NpZW5jZSBsaXRlcmFjeSwgaWxsdXNpb24gb2Yga25vd2xlZGdlLCBhbmQgcG9saXRpY2FsIG9yaWVudGF0aW9uIGluIGNsaW1hdGUgY2hhbmdlIHNrZXB0aWNpc20uCgotIFdpY2toYW0sIEguICgyMDE0KS4gVGlkeSBkYXRhLiBKb3VybmFsIG9mIFN0YXRpc3RpY2FsIFNvZnR3YXJlLCA1OSgxMCksIDEtMjMu